1 /* Copyright (c) 2012-2014, 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 
38 #include "QCamera3PostProc.h"
39 #include "QCamera3HWI.h"
40 #include "QCamera3Channel.h"
41 #include "QCamera3Stream.h"
42 
43 namespace qcamera {
44 
45 /*===========================================================================
46  * FUNCTION   : QCamera3PostProcessor
47  *
48  * DESCRIPTION: constructor of QCamera3PostProcessor.
49  *
50  * PARAMETERS :
51  *   @cam_ctrl : ptr to HWI object
52  *
53  * RETURN     : None
54  *==========================================================================*/
QCamera3PostProcessor(QCamera3PicChannel * ch_ctrl)55 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3PicChannel* ch_ctrl)
56     : m_parent(ch_ctrl),
57       mJpegCB(NULL),
58       mJpegUserData(NULL),
59       mJpegClientHandle(0),
60       mJpegSessionId(0),
61       m_bThumbnailNeeded(TRUE),
62       m_pReprocChannel(NULL),
63       m_inputPPQ(releasePPInputData, this),
64       m_inputFWKPPQ(NULL, this),
65       m_ongoingPPQ(releaseOngoingPPData, this),
66       m_inputJpegQ(releaseJpegData, this),
67       m_ongoingJpegQ(releaseJpegData, this),
68       m_inputRawQ(releasePPInputData, this),
69       m_inputMetaQ(releaseMetadata, this),
70       m_jpegSettingsQ(NULL, this)
71 {
72     memset(&mJpegHandle, 0, sizeof(mJpegHandle));
73     pthread_mutex_init(&mReprocJobLock, NULL);
74 }
75 
76 /*===========================================================================
77  * FUNCTION   : ~QCamera3PostProcessor
78  *
79  * DESCRIPTION: deconstructor of QCamera3PostProcessor.
80  *
81  * PARAMETERS : None
82  *
83  * RETURN     : None
84  *==========================================================================*/
~QCamera3PostProcessor()85 QCamera3PostProcessor::~QCamera3PostProcessor()
86 {
87     pthread_mutex_destroy(&mReprocJobLock);
88 }
89 
90 /*===========================================================================
91  * FUNCTION   : init
92  *
93  * DESCRIPTION: initialization of postprocessor
94  *
95  * PARAMETERS :
96  *   @jpeg_cb      : callback to handle jpeg event from mm-camera-interface
97  *   @user_data    : user data ptr for jpeg callback
98  *
99  * RETURN     : int32_t type of status
100  *              NO_ERROR  -- success
101  *              none-zero failure code
102  *==========================================================================*/
init(QCamera3Memory * mMemory,jpeg_encode_callback_t jpeg_cb,uint32_t postprocess_mask,void * user_data)103 int32_t QCamera3PostProcessor::init(QCamera3Memory* mMemory,
104                                     jpeg_encode_callback_t jpeg_cb,
105                                     uint32_t postprocess_mask,
106                                     void *user_data)
107 {
108     ATRACE_CALL();
109     mJpegCB = jpeg_cb;
110     mJpegUserData = user_data;
111     mm_dimension max_size;
112 
113     //set max pic size
114     memset(&max_size, 0, sizeof(mm_dimension));
115     max_size.w =  m_parent->m_max_pic_dim.width;
116     max_size.h =  m_parent->m_max_pic_dim.height;
117 
118     mJpegClientHandle = jpeg_open(&mJpegHandle,max_size);
119     mJpegMem = mMemory;
120     if(!mJpegClientHandle) {
121         ALOGE("%s : jpeg_open did not work", __func__);
122         return UNKNOWN_ERROR;
123     }
124     mPostProcMask = postprocess_mask;
125     m_dataProcTh.launch(dataProcessRoutine, this);
126 
127     return NO_ERROR;
128 }
129 
130 /*===========================================================================
131  * FUNCTION   : deinit
132  *
133  * DESCRIPTION: de-initialization of postprocessor
134  *
135  * PARAMETERS : None
136  *
137  * RETURN     : int32_t type of status
138  *              NO_ERROR  -- success
139  *              none-zero failure code
140  *==========================================================================*/
deinit()141 int32_t QCamera3PostProcessor::deinit()
142 {
143     m_dataProcTh.exit();
144 
145     if (m_pReprocChannel != NULL) {
146         m_pReprocChannel->stop();
147         delete m_pReprocChannel;
148         m_pReprocChannel = NULL;
149     }
150 
151     if(mJpegClientHandle > 0) {
152         int rc = mJpegHandle.close(mJpegClientHandle);
153         CDBG_HIGH("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
154               __func__, rc, mJpegClientHandle);
155         mJpegClientHandle = 0;
156         memset(&mJpegHandle, 0, sizeof(mJpegHandle));
157     }
158 
159     mJpegMem = NULL;
160 
161     return NO_ERROR;
162 }
163 
164 /*===========================================================================
165  * FUNCTION   : start
166  *
167  * DESCRIPTION: start postprocessor. Data process thread and data notify thread
168  *              will be launched.
169  *
170  * PARAMETERS :
171  *   @pMemory       : memory object representing buffers to store JPEG.
172  *   @config        : reprocess configuration
173  *   @metadata      : metadata for the reprocessing
174  *
175  * RETURN     : int32_t type of status
176  *              NO_ERROR  -- success
177  *              none-zero failure code
178  *
179  * NOTE       : if any reprocess is needed, a reprocess channel/stream
180  *              will be started.
181  *==========================================================================*/
start(const reprocess_config_t & config,metadata_buffer_t * metadata)182 int32_t QCamera3PostProcessor::start(const reprocess_config_t &config,
183         metadata_buffer_t *metadata)
184 {
185     int32_t rc = NO_ERROR;
186     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
187 
188     if (hal_obj->needReprocess(mPostProcMask)) {
189         if (m_pReprocChannel != NULL) {
190             m_pReprocChannel->stop();
191             delete m_pReprocChannel;
192             m_pReprocChannel = NULL;
193         }
194 
195         // if reprocess is needed, start reprocess channel
196         QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
197         CDBG("%s: Setting input channel as pInputChannel", __func__);
198         m_pReprocChannel = hal_obj->addOfflineReprocChannel(config, m_parent, metadata);
199         if (m_pReprocChannel == NULL) {
200             ALOGE("%s: cannot add reprocess channel", __func__);
201             return UNKNOWN_ERROR;
202         }
203 
204         rc = m_pReprocChannel->start();
205         if (rc != 0) {
206             ALOGE("%s: cannot start reprocess channel", __func__);
207             delete m_pReprocChannel;
208             m_pReprocChannel = NULL;
209             return rc;
210         }
211     }
212     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE);
213 
214     return rc;
215 }
216 
217 /*===========================================================================
218  * FUNCTION   : stop
219  *
220  * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
221  *
222  * PARAMETERS : None
223  *
224  * RETURN     : int32_t type of status
225  *              NO_ERROR  -- success
226  *              none-zero failure code
227  *
228  * NOTE       : reprocess channel will be stopped and deleted if there is any
229  *==========================================================================*/
stop()230 int32_t QCamera3PostProcessor::stop()
231 {
232     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
233 
234     if (m_pReprocChannel != NULL) {
235         m_pReprocChannel->stop();
236         delete m_pReprocChannel;
237         m_pReprocChannel = NULL;
238     }
239 
240     return NO_ERROR;
241 }
242 
243 /*===========================================================================
244  * FUNCTION   : getFWKJpegEncodeConfig
245  *
246  * DESCRIPTION: function to prepare encoding job information
247  *
248  * PARAMETERS :
249  *   @encode_parm   : param to be filled with encoding configuration
250  *   @frame         : framework input buffer
251  *   @jpeg_settings : jpeg settings to be applied for encoding
252  *
253  * RETURN     : int32_t type of status
254  *              NO_ERROR  -- success
255  *              none-zero failure code
256  *==========================================================================*/
getFWKJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,qcamera_fwk_input_pp_data_t * frame,jpeg_settings_t * jpeg_settings)257 int32_t QCamera3PostProcessor::getFWKJpegEncodeConfig(
258         mm_jpeg_encode_params_t& encode_parm,
259         qcamera_fwk_input_pp_data_t *frame,
260         jpeg_settings_t *jpeg_settings)
261 {
262     CDBG("%s : E", __func__);
263     int32_t ret = NO_ERROR;
264 
265     if ((NULL == frame) || (NULL == jpeg_settings)) {
266         return BAD_VALUE;
267     }
268 
269     encode_parm.jpeg_cb = mJpegCB;
270     encode_parm.userdata = mJpegUserData;
271 
272     if (jpeg_settings->thumbnail_size.width > 0 &&
273             jpeg_settings->thumbnail_size.height > 0)
274         m_bThumbnailNeeded = TRUE;
275     else
276         m_bThumbnailNeeded = FALSE;
277     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
278 
279     // get color format
280     cam_format_t img_fmt = frame->reproc_config.stream_format;
281     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
282 
283     // get jpeg quality
284     encode_parm.quality = jpeg_settings->jpeg_quality;
285     if (encode_parm.quality <= 0) {
286         encode_parm.quality = 85;
287     }
288 
289     // get jpeg thumbnail quality
290     encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
291 
292     cam_frame_len_offset_t main_offset =
293             frame->reproc_config.input_stream_plane_info.plane_info;
294 
295     encode_parm.num_src_bufs = 1;
296     encode_parm.src_main_buf[0].index = 0;
297     encode_parm.src_main_buf[0].buf_size = frame->input_buffer.frame_len;
298     encode_parm.src_main_buf[0].buf_vaddr = (uint8_t *) frame->input_buffer.buffer;
299     encode_parm.src_main_buf[0].fd = frame->input_buffer.fd;
300     encode_parm.src_main_buf[0].format = MM_JPEG_FMT_YUV;
301     encode_parm.src_main_buf[0].offset = main_offset;
302 
303     //Pass input thumbnail buffer info to encoder.
304     //Note: Use main buffer to encode thumbnail
305     if (m_bThumbnailNeeded == TRUE) {
306         encode_parm.num_tmb_bufs = 1;
307         encode_parm.src_thumb_buf[0] = encode_parm.src_main_buf[0];
308     }
309 
310     //Pass output jpeg buffer info to encoder.
311     //mJpegMem is allocated by framework.
312     encode_parm.num_dst_bufs = 1;
313     encode_parm.dest_buf[0].index = 0;
314     encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(
315             jpeg_settings->out_buf_index);
316     encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(
317             jpeg_settings->out_buf_index);
318     encode_parm.dest_buf[0].fd = mJpegMem->getFd(
319             jpeg_settings->out_buf_index);
320     encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
321     encode_parm.dest_buf[0].offset = main_offset;
322 
323     CDBG("%s : X", __func__);
324     return NO_ERROR;
325 
326 on_error:
327     CDBG("%s : X with error %d", __func__, ret);
328     return ret;
329 }
330 
331 /*===========================================================================
332  * FUNCTION   : getJpegEncodeConfig
333  *
334  * DESCRIPTION: function to prepare encoding job information
335  *
336  * PARAMETERS :
337  *   @encode_parm   : param to be filled with encoding configuration
338  *   #main_stream   : stream object where the input buffer comes from
339  *   @jpeg_settings : jpeg settings to be applied for encoding
340  *
341  * RETURN     : int32_t type of status
342  *              NO_ERROR  -- success
343  *              none-zero failure code
344  *==========================================================================*/
getJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,QCamera3Stream * main_stream,jpeg_settings_t * jpeg_settings)345 int32_t QCamera3PostProcessor::getJpegEncodeConfig(
346                 mm_jpeg_encode_params_t& encode_parm,
347                 QCamera3Stream *main_stream,
348                 jpeg_settings_t *jpeg_settings)
349 {
350     CDBG("%s : E", __func__);
351     int32_t ret = NO_ERROR;
352 
353     encode_parm.jpeg_cb = mJpegCB;
354     encode_parm.userdata = mJpegUserData;
355 
356     if (jpeg_settings->thumbnail_size.width > 0 &&
357             jpeg_settings->thumbnail_size.height > 0)
358         m_bThumbnailNeeded = TRUE;
359     else
360         m_bThumbnailNeeded = FALSE;
361     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
362 
363     // get color format
364     cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12;  //default value
365     main_stream->getFormat(img_fmt);
366     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
367 
368     //get rotation
369     encode_parm.jpeg_orientation = jpeg_settings->jpeg_orientation;
370 
371     // get jpeg quality
372     encode_parm.quality = jpeg_settings->jpeg_quality;
373     if (encode_parm.quality <= 0) {
374         encode_parm.quality = 85;
375     }
376 
377     // get jpeg thumbnail quality
378     encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
379 
380     cam_frame_len_offset_t main_offset;
381     memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
382     main_stream->getFrameOffset(main_offset);
383 
384     // src buf config
385     //Pass input main image buffer info to encoder.
386     QCamera3Memory *pStreamMem = main_stream->getStreamBufs();
387     if (pStreamMem == NULL) {
388         ALOGE("%s: cannot get stream bufs from main stream", __func__);
389         ret = BAD_VALUE;
390         goto on_error;
391     }
392     encode_parm.num_src_bufs = pStreamMem->getCnt();
393     for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
394         if (pStreamMem != NULL) {
395             encode_parm.src_main_buf[i].index = i;
396             encode_parm.src_main_buf[i].buf_size = pStreamMem->getSize(i);
397             encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
398             encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
399             encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
400             encode_parm.src_main_buf[i].offset = main_offset;
401         }
402     }
403 
404     //Pass input thumbnail buffer info to encoder.
405     //Note: Use main buffer to encode thumbnail
406     if (m_bThumbnailNeeded == TRUE) {
407         pStreamMem = main_stream->getStreamBufs();
408         if (pStreamMem == NULL) {
409             ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
410             ret = BAD_VALUE;
411             goto on_error;
412         }
413         cam_frame_len_offset_t thumb_offset;
414         memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
415         main_stream->getFrameOffset(thumb_offset);
416         encode_parm.num_tmb_bufs = pStreamMem->getCnt();
417         for (int i = 0; i < pStreamMem->getCnt(); i++) {
418             if (pStreamMem != NULL) {
419                 encode_parm.src_thumb_buf[i].index = i;
420                 encode_parm.src_thumb_buf[i].buf_size = pStreamMem->getSize(i);
421                 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
422                 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
423                 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
424                 encode_parm.src_thumb_buf[i].offset = thumb_offset;
425             }
426         }
427     }
428 
429     //Pass output jpeg buffer info to encoder.
430     //mJpegMem is allocated by framework.
431     encode_parm.num_dst_bufs = 1;
432     encode_parm.dest_buf[0].index = 0;
433     encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(
434             jpeg_settings->out_buf_index);
435     encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(
436             jpeg_settings->out_buf_index);
437     encode_parm.dest_buf[0].fd = mJpegMem->getFd(
438             jpeg_settings->out_buf_index);
439     encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
440     encode_parm.dest_buf[0].offset = main_offset;
441 
442     CDBG("%s : X", __func__);
443     return NO_ERROR;
444 
445 on_error:
446     CDBG("%s : X with error %d", __func__, ret);
447     return ret;
448 }
449 
450 /*===========================================================================
451  * FUNCTION   : processData
452  *
453  * DESCRIPTION: enqueue data into dataProc thread
454  *
455  * PARAMETERS :
456  *   @frame   : process frame
457  *
458  * RETURN     : int32_t type of status
459  *              NO_ERROR  -- success
460  *              none-zero failure code
461  *
462  * NOTE       : depends on if offline reprocess is needed, received frame will
463  *              be sent to either input queue of postprocess or jpeg encoding
464  *==========================================================================*/
processData(mm_camera_super_buf_t * frame)465 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame)
466 {
467     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
468     pthread_mutex_lock(&mReprocJobLock);
469     // enqueue to post proc input queue
470     m_inputPPQ.enqueue((void *)frame);
471     if (!(m_inputMetaQ.isEmpty())) {
472        CDBG("%s: meta queue is not empty, do next job", __func__);
473        m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
474     }
475     pthread_mutex_unlock(&mReprocJobLock);
476 
477     return NO_ERROR;
478 }
479 
480 /*===========================================================================
481  * FUNCTION   : processData
482  *
483  * DESCRIPTION: enqueue data into dataProc thread
484  *
485  * PARAMETERS :
486  *   @frame   : process frame
487  *
488  * RETURN     : int32_t type of status
489  *              NO_ERROR  -- success
490  *              none-zero failure code
491  *
492  * NOTE       : depends on if offline reprocess is needed, received frame will
493  *              be sent to either input queue of postprocess or jpeg encoding
494  *==========================================================================*/
processData(qcamera_fwk_input_pp_data_t * frame)495 int32_t QCamera3PostProcessor::processData(qcamera_fwk_input_pp_data_t *frame)
496 {
497     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
498     if (hal_obj->needReprocess(mPostProcMask)) {
499         pthread_mutex_lock(&mReprocJobLock);
500         // enqueu to post proc input queue
501         m_inputFWKPPQ.enqueue((void *)frame);
502         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
503         pthread_mutex_unlock(&mReprocJobLock);
504     } else {
505         jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue();
506 
507         if (jpeg_settings == NULL) {
508             ALOGE("%s: Cannot find jpeg settings", __func__);
509             return BAD_VALUE;
510         }
511 
512         CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__);
513         qcamera_hal3_jpeg_data_t *jpeg_job =
514             (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
515         if (jpeg_job == NULL) {
516             ALOGE("%s: No memory for jpeg job", __func__);
517             return NO_MEMORY;
518         }
519 
520         memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
521         jpeg_job->fwk_frame = frame;
522         jpeg_job->jpeg_settings = jpeg_settings;
523         jpeg_job->metadata =
524                 (metadata_buffer_t *) frame->metadata_buffer.buffer;
525 
526         // enqueu to jpeg input queue
527         m_inputJpegQ.enqueue((void *)jpeg_job);
528         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
529     }
530 
531     return NO_ERROR;
532 }
533 
534 /*===========================================================================
535  * FUNCTION   : processPPMetadata
536  *
537  * DESCRIPTION: enqueue data into dataProc thread
538  *
539  * PARAMETERS :
540  *   @frame   : process metadata frame received from pic channel
541  *
542  * RETURN     : int32_t type of status
543  *              NO_ERROR  -- success
544  *              none-zero failure code
545  *
546  *==========================================================================*/
processPPMetadata(mm_camera_super_buf_t * reproc_meta)547 int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta)
548 {
549    pthread_mutex_lock(&mReprocJobLock);
550     // enqueue to metadata input queue
551     m_inputMetaQ.enqueue((void *)reproc_meta);
552     if (!(m_inputPPQ.isEmpty())) {
553        CDBG("%s: pp queue is not empty, do next job", __func__);
554        m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
555     } else {
556        CDBG("%s: pp queue is empty, not calling do next job", __func__);
557     }
558     pthread_mutex_unlock(&mReprocJobLock);
559     return NO_ERROR;
560 }
561 
562 /*===========================================================================
563  * FUNCTION   : processJpegSettingData
564  *
565  * DESCRIPTION: enqueue jpegSetting into dataProc thread
566  *
567  * PARAMETERS :
568  *   @jpeg_settings : jpeg settings data received from pic channel
569  *
570  * RETURN     : int32_t type of status
571  *              NO_ERROR  -- success
572  *              none-zero failure code
573  *
574  *==========================================================================*/
processJpegSettingData(jpeg_settings_t * jpeg_settings)575 int32_t QCamera3PostProcessor::processJpegSettingData(
576         jpeg_settings_t *jpeg_settings)
577 {
578     if (!jpeg_settings) {
579         ALOGE("%s: invalid jpeg settings pointer", __func__);
580         return -EINVAL;
581     }
582     return m_jpegSettingsQ.enqueue((void *)jpeg_settings);
583 }
584 
585 /*===========================================================================
586  * FUNCTION   : processRawData
587  *
588  * DESCRIPTION: enqueue raw data into dataProc thread
589  *
590  * PARAMETERS :
591  *   @frame   : process frame received from mm-camera-interface
592  *
593  * RETURN     : int32_t type of status
594  *              NO_ERROR  -- success
595  *              none-zero failure code
596  *==========================================================================*/
processRawData(mm_camera_super_buf_t * frame)597 int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame)
598 {
599     // enqueu to raw input queue
600     m_inputRawQ.enqueue((void *)frame);
601     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
602     return NO_ERROR;
603 }
604 
605 /*===========================================================================
606  * FUNCTION   : processPPData
607  *
608  * DESCRIPTION: process received frame after reprocess.
609  *
610  * PARAMETERS :
611  *   @frame   : received frame from reprocess channel.
612  *
613  * RETURN     : int32_t type of status
614  *              NO_ERROR  -- success
615  *              none-zero failure code
616  *
617  * NOTE       : The frame after reprocess need to send to jpeg encoding.
618  *==========================================================================*/
processPPData(mm_camera_super_buf_t * frame)619 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame)
620 {
621     qcamera_hal3_pp_data_t *job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
622 
623     if (job == NULL || ((NULL == job->src_frame) && (NULL == job->fwk_src_frame))) {
624         ALOGE("%s: Cannot find reprocess job", __func__);
625         return BAD_VALUE;
626     }
627     if (job->jpeg_settings == NULL) {
628         ALOGE("%s: Cannot find jpeg settings", __func__);
629         return BAD_VALUE;
630     }
631 
632     qcamera_hal3_jpeg_data_t *jpeg_job =
633         (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
634     if (jpeg_job == NULL) {
635         ALOGE("%s: No memory for jpeg job", __func__);
636         return NO_MEMORY;
637     }
638 
639     memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
640     jpeg_job->src_frame = frame;
641     if(frame != job->src_frame)
642         jpeg_job->src_reproc_frame = job->src_frame;
643     if (NULL == job->fwk_src_frame) {
644         jpeg_job->metadata = job->metadata;
645     } else {
646         jpeg_job->metadata =
647                 (metadata_buffer_t *) job->fwk_src_frame->metadata_buffer.buffer;
648         jpeg_job->fwk_src_buffer = job->fwk_src_frame;
649     }
650     jpeg_job->src_metadata = job->src_metadata;
651     jpeg_job->jpeg_settings = job->jpeg_settings;
652 
653     // free pp job buf
654     free(job);
655 
656     // enqueu reprocessed frame to jpeg input queue
657     m_inputJpegQ.enqueue((void *)jpeg_job);
658 
659     // wait up data proc thread
660     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
661 
662     return NO_ERROR;
663 }
664 
665 /*===========================================================================
666  * FUNCTION   : findJpegJobByJobId
667  *
668  * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
669  *
670  * PARAMETERS :
671  *   @jobId   : job Id of the job
672  *
673  * RETURN     : ptr to a jpeg job struct. NULL if not found.
674  *
675  * NOTE       : Currently only one job is sending to mm-jpeg-interface for jpeg
676  *              encoding. Therefore simply dequeue from the ongoing Jpeg Queue
677  *              will serve the purpose to find the jpeg job.
678  *==========================================================================*/
findJpegJobByJobId(uint32_t jobId)679 qcamera_hal3_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId)
680 {
681     qcamera_hal3_jpeg_data_t * job = NULL;
682     if (jobId == 0) {
683         ALOGE("%s: not a valid jpeg jobId", __func__);
684         return NULL;
685     }
686 
687     // currely only one jpeg job ongoing, so simply dequeue the head
688     job = (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
689     return job;
690 }
691 
692 /*===========================================================================
693  * FUNCTION   : releasePPInputData
694  *
695  * DESCRIPTION: callback function to release post process input data node
696  *
697  * PARAMETERS :
698  *   @data      : ptr to post process input data
699  *   @user_data : user data ptr (QCamera3Reprocessor)
700  *
701  * RETURN     : None
702  *==========================================================================*/
releasePPInputData(void * data,void * user_data)703 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data)
704 {
705     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
706     if (NULL != pme) {
707         pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
708     }
709 }
710 
711 /*===========================================================================
712  * FUNCTION   : releaseMetaData
713  *
714  * DESCRIPTION: callback function to release metadata camera buffer
715  *
716  * PARAMETERS :
717  *   @data      : ptr to post process input data
718  *   @user_data : user data ptr (QCamera3Reprocessor)
719  *
720  * RETURN     : None
721  *==========================================================================*/
releaseMetadata(void * data,void * user_data)722 void QCamera3PostProcessor::releaseMetadata(void *data, void *user_data)
723 {
724     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
725     if (NULL != pme) {
726         pme->m_parent->metadataBufDone((mm_camera_super_buf_t *)data);
727     }
728 }
729 
730 /*===========================================================================
731  * FUNCTION   : releaseJpegData
732  *
733  * DESCRIPTION: callback function to release jpeg job node
734  *
735  * PARAMETERS :
736  *   @data      : ptr to ongoing jpeg job data
737  *   @user_data : user data ptr (QCamera3Reprocessor)
738  *
739  * RETURN     : None
740  *==========================================================================*/
releaseJpegData(void * data,void * user_data)741 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data)
742 {
743     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
744     if (NULL != pme) {
745         pme->releaseJpegJobData((qcamera_hal3_jpeg_data_t *)data);
746     }
747 }
748 
749 /*===========================================================================
750  * FUNCTION   : releaseOngoingPPData
751  *
752  * DESCRIPTION: callback function to release ongoing postprocess job node
753  *
754  * PARAMETERS :
755  *   @data      : ptr to onging postprocess job
756  *   @user_data : user data ptr (QCamera3Reprocessor)
757  *
758  * RETURN     : None
759  *==========================================================================*/
releaseOngoingPPData(void * data,void * user_data)760 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data)
761 {
762     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
763     if (NULL != pme) {
764         qcamera_hal3_pp_data_t *pp_job = (qcamera_hal3_pp_data_t *)data;
765         if (NULL != pp_job->src_frame) {
766             pme->releaseSuperBuf(pp_job->src_frame);
767             free(pp_job->src_frame);
768             if (NULL != pp_job->src_metadata) {
769                 pme->m_parent->metadataBufDone(pp_job->src_metadata);
770                 free(pp_job->src_metadata);
771             }
772             pp_job->src_frame = NULL;
773             pp_job->metadata = NULL;
774         }
775 
776         if (NULL != pp_job->fwk_src_frame) {
777             free(pp_job->fwk_src_frame);
778             pp_job->fwk_src_frame = NULL;
779         }
780     }
781 }
782 
783 /*===========================================================================
784  * FUNCTION   : releaseSuperBuf
785  *
786  * DESCRIPTION: function to release a superbuf frame by returning back to kernel
787  *
788  * PARAMETERS :
789  *   @super_buf : ptr to the superbuf frame
790  *
791  * RETURN     : None
792  *==========================================================================*/
releaseSuperBuf(mm_camera_super_buf_t * super_buf)793 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
794 {
795     if (NULL != super_buf) {
796         if (m_parent != NULL) {
797             m_parent->bufDone(super_buf);
798         }
799     }
800 }
801 
802 /*===========================================================================
803  * FUNCTION   : releaseOfflineBuffers
804  *
805  * DESCRIPTION: function to release/unmap offline buffers if any
806  *
807  * PARAMETERS : None
808  *
809  * RETURN     : int32_t type of status
810  *              NO_ERROR  -- success
811  *              none-zero failure code
812  *==========================================================================*/
releaseOfflineBuffers()813 int32_t QCamera3PostProcessor::releaseOfflineBuffers()
814 {
815     int32_t rc = NO_ERROR;
816 
817     if(NULL != m_pReprocChannel) {
818         rc = m_pReprocChannel->unmapOfflineBuffers(false);
819     }
820 
821     return rc;
822 }
823 
824 /*===========================================================================
825  * FUNCTION   : releaseJpegJobData
826  *
827  * DESCRIPTION: function to release internal resources in jpeg job struct
828  *
829  * PARAMETERS :
830  *   @job     : ptr to jpeg job struct
831  *
832  * RETURN     : None
833  *
834  * NOTE       : original source frame need to be queued back to kernel for
835  *              future use. Output buf of jpeg job need to be released since
836  *              it's allocated for each job. Exif object need to be deleted.
837  *==========================================================================*/
releaseJpegJobData(qcamera_hal3_jpeg_data_t * job)838 void QCamera3PostProcessor::releaseJpegJobData(qcamera_hal3_jpeg_data_t *job)
839 {
840     ATRACE_CALL();
841     int32_t rc = NO_ERROR;
842     CDBG("%s: E", __func__);
843     if (NULL != job) {
844         if (NULL != job->src_reproc_frame) {
845             free(job->src_reproc_frame);
846             job->src_reproc_frame = NULL;
847         }
848 
849         if (NULL != job->src_frame) {
850             if (NULL != m_pReprocChannel) {
851                 rc = m_pReprocChannel->bufDone(job->src_frame);
852                 if (NO_ERROR != rc)
853                     ALOGE("%s: bufDone error: %d", __func__, rc);
854             }
855             free(job->src_frame);
856             job->src_frame = NULL;
857         }
858 
859         if (NULL != job->fwk_src_buffer) {
860             free(job->fwk_src_buffer);
861             job->fwk_src_buffer = NULL;
862         } else if (NULL != job->src_metadata) {
863             m_parent->metadataBufDone(job->src_metadata);
864             free(job->src_metadata);
865             job->src_metadata = NULL;
866         }
867 
868         if (NULL != job->fwk_frame) {
869             free(job->fwk_frame);
870             job->fwk_frame = NULL;
871         }
872 
873         if (NULL != job->pJpegExifObj) {
874             delete job->pJpegExifObj;
875             job->pJpegExifObj = NULL;
876         }
877 
878         if (NULL != job->jpeg_settings) {
879             free(job->jpeg_settings);
880             job->jpeg_settings = NULL;
881         }
882     }
883     /* Additional trigger to process any pending jobs in the input queue */
884     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
885     CDBG("%s: X", __func__);
886 }
887 
888 /*===========================================================================
889  * FUNCTION   : getColorfmtFromImgFmt
890  *
891  * DESCRIPTION: function to return jpeg color format based on its image format
892  *
893  * PARAMETERS :
894  *   @img_fmt : image format
895  *
896  * RETURN     : jpeg color format that can be understandable by omx lib
897  *==========================================================================*/
getColorfmtFromImgFmt(cam_format_t img_fmt)898 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
899 {
900     switch (img_fmt) {
901     case CAM_FORMAT_YUV_420_NV21:
902         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
903     case CAM_FORMAT_YUV_420_NV21_ADRENO:
904         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
905     case CAM_FORMAT_YUV_420_NV12:
906         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
907     case CAM_FORMAT_YUV_420_YV12:
908         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
909     case CAM_FORMAT_YUV_422_NV61:
910         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
911     case CAM_FORMAT_YUV_422_NV16:
912         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
913     default:
914         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
915     }
916 }
917 
918 /*===========================================================================
919  * FUNCTION   : getJpegImgTypeFromImgFmt
920  *
921  * DESCRIPTION: function to return jpeg encode image type based on its image format
922  *
923  * PARAMETERS :
924  *   @img_fmt : image format
925  *
926  * RETURN     : return jpeg source image format (YUV or Bitstream)
927  *==========================================================================*/
getJpegImgTypeFromImgFmt(cam_format_t img_fmt)928 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
929 {
930     switch (img_fmt) {
931     case CAM_FORMAT_YUV_420_NV21:
932     case CAM_FORMAT_YUV_420_NV21_ADRENO:
933     case CAM_FORMAT_YUV_420_NV12:
934     case CAM_FORMAT_YUV_420_YV12:
935     case CAM_FORMAT_YUV_422_NV61:
936     case CAM_FORMAT_YUV_422_NV16:
937         return MM_JPEG_FMT_YUV;
938     default:
939         return MM_JPEG_FMT_YUV;
940     }
941 }
942 
943 /*===========================================================================
944  * FUNCTION   : encodeFWKData
945  *
946  * DESCRIPTION: function to prepare encoding job information and send to
947  *              mm-jpeg-interface to do the encoding job
948  *
949  * PARAMETERS :
950  *   @jpeg_job_data : ptr to a struct saving job related information
951  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
952  *                    to be created. After creation, this flag will be toggled
953  *
954  * RETURN     : int32_t type of status
955  *              NO_ERROR  -- success
956  *              none-zero failure code
957  *==========================================================================*/
encodeFWKData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)958 int32_t QCamera3PostProcessor::encodeFWKData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
959         uint8_t &needNewSess)
960 {
961     CDBG("%s : E", __func__);
962     int32_t ret = NO_ERROR;
963     mm_jpeg_job_t jpg_job;
964     uint32_t jobId = 0;
965     qcamera_fwk_input_pp_data_t *recvd_frame = NULL;
966     metadata_buffer_t *metadata = NULL;
967     jpeg_settings_t *jpeg_settings = NULL;
968     QCamera3HardwareInterface* hal_obj = NULL;
969 
970     if (NULL == jpeg_job_data) {
971         ALOGE("%s: Invalid jpeg job", __func__);
972         return BAD_VALUE;
973     }
974 
975     recvd_frame = jpeg_job_data->fwk_frame;
976     if (NULL == recvd_frame) {
977         ALOGE("%s: Invalid input buffer", __func__);
978         return BAD_VALUE;
979     }
980 
981     metadata = jpeg_job_data->metadata;
982     if (NULL == metadata) {
983         ALOGE("%s: Invalid metadata buffer", __func__);
984         return BAD_VALUE;
985     }
986 
987     jpeg_settings = jpeg_job_data->jpeg_settings;
988     if (NULL == jpeg_settings) {
989         ALOGE("%s: Invalid jpeg settings buffer", __func__);
990         return BAD_VALUE;
991     }
992 
993     if ((NULL != jpeg_job_data->src_frame) && (NULL != jpeg_job_data->src_frame)) {
994         ALOGE("%s: Unsupported case both framework and camera source buffers are invalid!",
995                 __func__);
996         return BAD_VALUE;
997     }
998 
999     hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1000 
1001     if (mJpegClientHandle <= 0) {
1002         ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
1003         return UNKNOWN_ERROR;
1004     }
1005 
1006     cam_dimension_t src_dim;
1007     memset(&src_dim, 0, sizeof(cam_dimension_t));
1008     src_dim.width = recvd_frame->reproc_config.input_stream_dim.width;
1009     src_dim.height = recvd_frame->reproc_config.input_stream_dim.height;
1010 
1011     cam_dimension_t dst_dim;
1012     memset(&dst_dim, 0, sizeof(cam_dimension_t));
1013     dst_dim.width = recvd_frame->reproc_config.output_stream_dim.width;
1014     dst_dim.height = recvd_frame->reproc_config.output_stream_dim.height;
1015 
1016     CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
1017     if (needNewSess) {
1018         //creating a new session, so we must destroy the old one
1019         if ( 0 < mJpegSessionId ) {
1020             ret = mJpegHandle.destroy_session(mJpegSessionId);
1021             if (ret != NO_ERROR) {
1022                 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
1023                       __func__, mJpegSessionId);
1024                 return ret;
1025             }
1026             mJpegSessionId = 0;
1027         }
1028         // create jpeg encoding session
1029         mm_jpeg_encode_params_t encodeParam;
1030         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1031         encodeParam.main_dim.src_dim = src_dim;
1032         encodeParam.main_dim.dst_dim = dst_dim;
1033         encodeParam.thumb_dim.src_dim = src_dim;
1034         encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1035 
1036         getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings);
1037         CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
1038                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1039 
1040         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1041         if (ret != NO_ERROR) {
1042             ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
1043             return ret;
1044         }
1045         needNewSess = FALSE;
1046     }
1047 
1048     // Fill in new job
1049     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1050     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1051     jpg_job.encode_job.session_id = mJpegSessionId;
1052     jpg_job.encode_job.src_index = 0;
1053     jpg_job.encode_job.dst_index = 0;
1054 
1055     cam_rect_t crop;
1056     memset(&crop, 0, sizeof(cam_rect_t));
1057     //TBD_later - Zoom event removed in stream
1058     //main_stream->getCropInfo(crop);
1059 
1060     // main dim
1061     jpg_job.encode_job.main_dim.src_dim = src_dim;
1062     jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1063     jpg_job.encode_job.main_dim.crop = crop;
1064 
1065     // get exif data
1066     QCamera3Exif *pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings);
1067     jpeg_job_data->pJpegExifObj = pJpegExifObj;
1068     if (pJpegExifObj != NULL) {
1069         jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1070         jpg_job.encode_job.exif_info.numOfEntries =
1071             pJpegExifObj->getNumOfEntries();
1072     }
1073 
1074     // thumbnail dim
1075     CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
1076     if (m_bThumbnailNeeded == TRUE) {
1077         memset(&crop, 0, sizeof(cam_rect_t));
1078         jpg_job.encode_job.thumb_dim.dst_dim =
1079                 jpeg_settings->thumbnail_size;
1080 
1081         if (!hal_obj->needRotationReprocess()) {
1082             jpg_job.encode_job.rotation =
1083                     jpeg_settings->jpeg_orientation;
1084             CDBG_HIGH("%s: jpeg rotation is set to %d", __func__,
1085                     jpg_job.encode_job.rotation);
1086         } else if (jpeg_settings->jpeg_orientation  == 90 ||
1087                 jpeg_settings->jpeg_orientation == 270) {
1088             //swap the thumbnail destination width and height if it has
1089             //already been rotated
1090             int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1091             jpg_job.encode_job.thumb_dim.dst_dim.width =
1092                     jpg_job.encode_job.thumb_dim.dst_dim.height;
1093             jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1094         }
1095         jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1096         jpg_job.encode_job.thumb_dim.crop = crop;
1097         jpg_job.encode_job.thumb_index = 0;
1098     }
1099 
1100     if (metadata != NULL) {
1101        //Fill in the metadata passed as parameter
1102        jpg_job.encode_job.p_metadata = metadata;
1103     } else {
1104        ALOGE("%s: Metadata is null", __func__);
1105     }
1106 
1107     jpg_job.encode_job.hal_version = CAM_HAL_V3;
1108 
1109     //Start jpeg encoding
1110     ret = mJpegHandle.start_job(&jpg_job, &jobId);
1111     if (ret == NO_ERROR) {
1112         // remember job info
1113         jpeg_job_data->jobId = jobId;
1114     }
1115 
1116     CDBG("%s : X", __func__);
1117     return ret;
1118 }
1119 
1120 /*===========================================================================
1121  * FUNCTION   : encodeData
1122  *
1123  * DESCRIPTION: function to prepare encoding job information and send to
1124  *              mm-jpeg-interface to do the encoding job
1125  *
1126  * PARAMETERS :
1127  *   @jpeg_job_data : ptr to a struct saving job related information
1128  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
1129  *                    to be created. After creation, this flag will be toggled
1130  *
1131  * RETURN     : int32_t type of status
1132  *              NO_ERROR  -- success
1133  *              none-zero failure code
1134  *==========================================================================*/
encodeData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1135 int32_t QCamera3PostProcessor::encodeData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
1136                           uint8_t &needNewSess)
1137 {
1138     ATRACE_CALL();
1139     CDBG("%s : E", __func__);
1140     int32_t ret = NO_ERROR;
1141     mm_jpeg_job_t jpg_job;
1142     uint32_t jobId = 0;
1143     QCamera3Stream *main_stream = NULL;
1144     mm_camera_buf_def_t *main_frame = NULL;
1145     QCamera3Channel *srcChannel = NULL;
1146     mm_camera_super_buf_t *recvd_frame = NULL;
1147     metadata_buffer_t *metadata = NULL;
1148     jpeg_settings_t *jpeg_settings = NULL;
1149     QCamera3HardwareInterface* hal_obj = NULL;
1150     bool needJpegRotation = false;
1151 
1152     hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1153     recvd_frame = jpeg_job_data->src_frame;
1154     metadata = jpeg_job_data->metadata;
1155     jpeg_settings = jpeg_job_data->jpeg_settings;
1156 
1157     CDBG("%s: encoding bufIndex: %u", __func__,
1158         jpeg_job_data->src_frame->bufs[0]->buf_idx);
1159 
1160     QCamera3Channel *pChannel = NULL;
1161     // first check picture channel
1162     if (m_parent != NULL &&
1163         m_parent->getMyHandle() == recvd_frame->ch_id) {
1164         pChannel = m_parent;
1165     }
1166     // check reprocess channel if not found
1167     if (pChannel == NULL) {
1168         if (m_pReprocChannel != NULL &&
1169             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
1170             pChannel = m_pReprocChannel;
1171         }
1172     }
1173 
1174     srcChannel = pChannel;
1175 
1176     if (srcChannel == NULL) {
1177         ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here",
1178               __func__, recvd_frame->ch_id);
1179         return BAD_VALUE;
1180     }
1181 
1182     // find snapshot frame and thumnail frame
1183     //Note: In this version we will receive only snapshot frame.
1184     for (int i = 0; i < recvd_frame->num_bufs; i++) {
1185         QCamera3Stream *srcStream =
1186             srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
1187         if (srcStream != NULL) {
1188             switch (srcStream->getMyType()) {
1189             case CAM_STREAM_TYPE_SNAPSHOT:
1190             case CAM_STREAM_TYPE_OFFLINE_PROC:
1191                 main_stream = srcStream;
1192                 main_frame = recvd_frame->bufs[i];
1193                 break;
1194             default:
1195                 break;
1196             }
1197         }
1198     }
1199 
1200     if(NULL == main_frame){
1201        ALOGE("%s : Main frame is NULL", __func__);
1202        return BAD_VALUE;
1203     }
1204 
1205     QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info;
1206     if (NULL == memObj) {
1207         ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
1208         return NO_MEMORY;
1209     }
1210 
1211     // clean and invalidate cache ops through mem obj of the frame
1212     memObj->cleanInvalidateCache(main_frame->buf_idx);
1213 
1214     if (mJpegClientHandle <= 0) {
1215         ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
1216         return UNKNOWN_ERROR;
1217     }
1218     cam_dimension_t src_dim;
1219     memset(&src_dim, 0, sizeof(cam_dimension_t));
1220     main_stream->getFrameDimension(src_dim);
1221 
1222     cam_dimension_t dst_dim;
1223     memset(&dst_dim, 0, sizeof(cam_dimension_t));
1224     srcChannel->getStreamByIndex(0)->getFrameDimension(dst_dim);
1225 
1226     needJpegRotation = hal_obj->needJpegRotation();
1227     CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
1228     if (needNewSess) {
1229         //creating a new session, so we must destroy the old one
1230         if ( 0 < mJpegSessionId ) {
1231             ret = mJpegHandle.destroy_session(mJpegSessionId);
1232             if (ret != NO_ERROR) {
1233                 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
1234                       __func__, mJpegSessionId);
1235                 return ret;
1236             }
1237             mJpegSessionId = 0;
1238         }
1239         // create jpeg encoding session
1240         mm_jpeg_encode_params_t encodeParam;
1241         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1242         getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings);
1243         CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
1244                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1245         if (!needJpegRotation &&
1246             (jpeg_settings->jpeg_orientation == 90 ||
1247             jpeg_settings->jpeg_orientation == 270)) {
1248            //swap src width and height, stride and scanline due to rotation
1249            encodeParam.main_dim.src_dim.width = src_dim.height;
1250            encodeParam.main_dim.src_dim.height = src_dim.width;
1251            encodeParam.thumb_dim.src_dim.width = src_dim.height;
1252            encodeParam.thumb_dim.src_dim.height = src_dim.width;
1253 
1254            int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride;
1255            encodeParam.src_main_buf[0].offset.mp[0].stride =
1256               encodeParam.src_main_buf[0].offset.mp[0].scanline;
1257            encodeParam.src_main_buf[0].offset.mp[0].scanline = temp;
1258 
1259            temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride;
1260            encodeParam.src_thumb_buf[0].offset.mp[0].stride =
1261               encodeParam.src_thumb_buf[0].offset.mp[0].scanline;
1262            encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp;
1263         } else {
1264            encodeParam.main_dim.src_dim  = src_dim;
1265            encodeParam.thumb_dim.src_dim = src_dim;
1266         }
1267         encodeParam.main_dim.dst_dim = dst_dim;
1268         encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1269         if (needJpegRotation) {
1270            encodeParam.rotation = jpeg_settings->jpeg_orientation;
1271         }
1272 
1273 
1274         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1275         if (ret != NO_ERROR) {
1276             ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
1277             return ret;
1278         }
1279         needNewSess = FALSE;
1280     }
1281 
1282     // Fill in new job
1283     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1284     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1285     jpg_job.encode_job.session_id = mJpegSessionId;
1286     jpg_job.encode_job.src_index = main_frame->buf_idx;
1287     jpg_job.encode_job.dst_index = 0;
1288 
1289     if (needJpegRotation) {
1290         jpg_job.encode_job.rotation =
1291                 jpeg_settings->jpeg_orientation;
1292         CDBG("%s: %d: jpeg rotation is set to %d", __func__, __LINE__,
1293                 jpg_job.encode_job.rotation);
1294     }
1295 
1296     cam_rect_t crop;
1297     memset(&crop, 0, sizeof(cam_rect_t));
1298     //TBD_later - Zoom event removed in stream
1299     //main_stream->getCropInfo(crop);
1300 
1301     // main dim
1302     jpg_job.encode_job.main_dim.src_dim = src_dim;
1303     jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1304     jpg_job.encode_job.main_dim.crop = crop;
1305 
1306     // get exif data
1307     QCamera3Exif *pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings);
1308     jpeg_job_data->pJpegExifObj = pJpegExifObj;
1309     if (pJpegExifObj != NULL) {
1310         jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1311         jpg_job.encode_job.exif_info.numOfEntries =
1312             pJpegExifObj->getNumOfEntries();
1313     }
1314 
1315     // thumbnail dim
1316     CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
1317     if (m_bThumbnailNeeded == TRUE) {
1318         memset(&crop, 0, sizeof(cam_rect_t));
1319         jpg_job.encode_job.thumb_dim.dst_dim =
1320                 jpeg_settings->thumbnail_size;
1321 
1322       if (!needJpegRotation &&
1323           (jpeg_settings->jpeg_orientation  == 90 ||
1324            jpeg_settings->jpeg_orientation == 270)) {
1325             //swap the thumbnail destination width and height if it has
1326             //already been rotated
1327             int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1328             jpg_job.encode_job.thumb_dim.dst_dim.width =
1329                     jpg_job.encode_job.thumb_dim.dst_dim.height;
1330             jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1331 
1332             jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height;
1333             jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width;
1334         } else {
1335            jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1336         }
1337         jpg_job.encode_job.thumb_dim.crop = crop;
1338         jpg_job.encode_job.thumb_index = main_frame->buf_idx;
1339     }
1340 
1341     if (metadata != NULL) {
1342        //Fill in the metadata passed as parameter
1343        jpg_job.encode_job.p_metadata = metadata;
1344     } else {
1345        ALOGE("%s: Metadata is null", __func__);
1346     }
1347 
1348     jpg_job.encode_job.hal_version = CAM_HAL_V3;
1349 
1350     //Start jpeg encoding
1351     ret = mJpegHandle.start_job(&jpg_job, &jobId);
1352     if (ret == NO_ERROR) {
1353         // remember job info
1354         jpeg_job_data->jobId = jobId;
1355     }
1356 
1357     CDBG("%s : X", __func__);
1358     return ret;
1359 }
1360 
1361 /*===========================================================================
1362  * FUNCTION   : dataProcessRoutine
1363  *
1364  * DESCRIPTION: data process routine that handles input data either from input
1365  *              Jpeg Queue to do jpeg encoding, or from input PP Queue to do
1366  *              reprocess.
1367  *
1368  * PARAMETERS :
1369  *   @data    : user data ptr (QCamera3PostProcessor)
1370  *
1371  * RETURN     : None
1372  *==========================================================================*/
dataProcessRoutine(void * data)1373 void *QCamera3PostProcessor::dataProcessRoutine(void *data)
1374 {
1375     int running = 1;
1376     int ret;
1377     uint8_t is_active = FALSE;
1378     uint8_t needNewSess = TRUE;
1379     mm_camera_super_buf_t *meta_buffer = NULL;
1380     CDBG("%s: E", __func__);
1381     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
1382     QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
1383     cmdThread->setName("cam_data_proc");
1384 
1385     do {
1386         do {
1387             ret = cam_sem_wait(&cmdThread->cmd_sem);
1388             if (ret != 0 && errno != EINVAL) {
1389                 ALOGE("%s: cam_sem_wait error (%s)",
1390                            __func__, strerror(errno));
1391                 return NULL;
1392             }
1393         } while (ret != 0);
1394 
1395         // we got notified about new cmd avail in cmd queue
1396         camera_cmd_type_t cmd = cmdThread->getCmd();
1397         switch (cmd) {
1398         case CAMERA_CMD_TYPE_START_DATA_PROC:
1399             CDBG_HIGH("%s: start data proc", __func__);
1400             is_active = TRUE;
1401             needNewSess = TRUE;
1402 
1403             pme->m_ongoingPPQ.init();
1404             pme->m_inputJpegQ.init();
1405             pme->m_inputPPQ.init();
1406             pme->m_inputFWKPPQ.init();
1407             pme->m_inputRawQ.init();
1408             pme->m_inputMetaQ.init();
1409 
1410             break;
1411         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
1412             {
1413                 CDBG_HIGH("%s: stop data proc", __func__);
1414                 is_active = FALSE;
1415 
1416                 // cancel all ongoing jpeg jobs
1417                 qcamera_hal3_jpeg_data_t *jpeg_job =
1418                     (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1419                 while (jpeg_job != NULL) {
1420                     pme->mJpegHandle.abort_job(jpeg_job->jobId);
1421 
1422                     pme->releaseJpegJobData(jpeg_job);
1423                     free(jpeg_job);
1424 
1425                     jpeg_job = (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1426                 }
1427 
1428                 // destroy jpeg encoding session
1429                 if ( 0 < pme->mJpegSessionId ) {
1430                     pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
1431                     pme->mJpegSessionId = 0;
1432                 }
1433 
1434                 needNewSess = TRUE;
1435 
1436                 // flush ongoing postproc Queue
1437                 pme->m_ongoingPPQ.flush();
1438 
1439                 // flush input jpeg Queue
1440                 pme->m_inputJpegQ.flush();
1441 
1442                 // flush input Postproc Queue
1443                 pme->m_inputPPQ.flush();
1444 
1445                 // flush framework input Postproc Queue
1446                 pme->m_inputFWKPPQ.flush();
1447 
1448                 // flush input raw Queue
1449                 pme->m_inputRawQ.flush();
1450 
1451                 pme->m_inputMetaQ.flush();
1452 
1453                 // signal cmd is completed
1454                 cam_sem_post(&cmdThread->sync_sem);
1455             }
1456             break;
1457         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
1458             {
1459                 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
1460                 /* needNewSess is set to TRUE as postproc is not re-STARTed
1461                  * anymore for every captureRequest */
1462                 needNewSess = TRUE;
1463                 if (is_active == TRUE) {
1464                     // check if there is any ongoing jpeg jobs
1465                     if (pme->m_ongoingJpegQ.isEmpty()) {
1466                        CDBG("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
1467                         // no ongoing jpeg job, we are fine to send jpeg encoding job
1468                         qcamera_hal3_jpeg_data_t *jpeg_job =
1469                             (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1470 
1471                         if (NULL != jpeg_job) {
1472                             // add into ongoing jpeg job Q
1473                             pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
1474 
1475                             if (jpeg_job->fwk_frame) {
1476                                 ret = pme->encodeFWKData(jpeg_job, needNewSess);
1477                             } else {
1478                                 ret = pme->encodeData(jpeg_job, needNewSess);
1479                             }
1480                             if (NO_ERROR != ret) {
1481                                 // dequeue the last one
1482                                 pme->m_ongoingJpegQ.dequeue(false);
1483 
1484                                 pme->releaseJpegJobData(jpeg_job);
1485                                 free(jpeg_job);
1486                             }
1487                         }
1488                     }
1489 
1490                     // check if there are any framework pp jobs
1491                     if (!pme->m_inputFWKPPQ.isEmpty()) {
1492                         qcamera_fwk_input_pp_data_t *fwk_frame =
1493                                 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
1494                         if (NULL != fwk_frame) {
1495                             qcamera_hal3_pp_data_t *pp_job =
1496                                     (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
1497                             jpeg_settings_t *jpeg_settings =
1498                                     (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
1499                             if (pp_job != NULL) {
1500                                 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
1501                                 pp_job->jpeg_settings = jpeg_settings;
1502                                 if (pme->m_pReprocChannel != NULL) {
1503                                    if (NO_ERROR != pme->m_pReprocChannel->extractCrop(fwk_frame)) {
1504                                        ALOGE("%s: Failed to extract output crop", __func__);
1505 	                            }
1506                                     // add into ongoing PP job Q
1507                                     pp_job->fwk_src_frame = fwk_frame;
1508                                     pme->m_ongoingPPQ.enqueue((void *)pp_job);
1509                                     ret = pme->m_pReprocChannel->doReprocessOffline(fwk_frame);
1510                                     if (NO_ERROR != ret) {
1511                                         // remove from ongoing PP job Q
1512                                         pme->m_ongoingPPQ.dequeue(false);
1513                                     }
1514                                 } else {
1515                                     ALOGE("%s: Reprocess channel is NULL", __func__);
1516                                     ret = -1;
1517                                 }
1518                             } else {
1519                                 ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__);
1520                                 ret = -1;
1521                             }
1522 
1523                             if (0 != ret) {
1524                                 // free pp_job
1525                                 if (pp_job != NULL) {
1526                                     free(pp_job);
1527                                 }
1528                                 // free frame
1529                                 if (fwk_frame != NULL) {
1530                                     free(fwk_frame);
1531                                 }
1532                             }
1533                         }
1534                     }
1535 
1536                     CDBG_HIGH("%s: dequeuing pp frame", __func__);
1537                     pthread_mutex_lock(&pme->mReprocJobLock);
1538                     if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) {
1539                         mm_camera_super_buf_t *pp_frame =
1540                             (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
1541                         meta_buffer =
1542                             (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
1543                         jpeg_settings_t *jpeg_settings =
1544                            (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
1545                         pthread_mutex_unlock(&pme->mReprocJobLock);
1546                         qcamera_hal3_pp_data_t *pp_job =
1547                             (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
1548                         if (pp_job != NULL) {
1549                             memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
1550                             pp_job->src_frame = pp_frame;
1551                             pp_job->src_metadata = meta_buffer;
1552                             pp_job->metadata =
1553                                     (metadata_buffer_t *)meta_buffer->bufs[0]->buffer;
1554                             pp_job->jpeg_settings = jpeg_settings;
1555                             pme->m_ongoingPPQ.enqueue((void *)pp_job);
1556                             if (pme->m_pReprocChannel != NULL) {
1557                                 qcamera_fwk_input_pp_data_t fwk_frame;
1558                                 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
1559                                 ret = pme->m_pReprocChannel->extractFrameCropAndRotation(
1560                                         pp_frame, meta_buffer->bufs[0],
1561                                         pp_job->jpeg_settings,
1562                                         fwk_frame);
1563                                 if (NO_ERROR == ret) {
1564                                     // add into ongoing PP job Q
1565                                     ret = pme->m_pReprocChannel->doReprocessOffline(
1566                                             &fwk_frame);
1567                                     if (NO_ERROR != ret) {
1568                                         // remove from ongoing PP job Q
1569                                         pme->m_ongoingPPQ.dequeue(false);
1570                                     }
1571                                 }
1572                             } else {
1573                                 CDBG_HIGH("%s: No reprocess. Calling processPPData directly",
1574                                     __func__);
1575                                 ret = pme->processPPData(pp_frame);
1576                             }
1577                         } else {
1578                             ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__);
1579                             ret = -1;
1580                         }
1581 
1582                         if (0 != ret) {
1583                             // free pp_job
1584                             if (pp_job != NULL) {
1585                                 free(pp_job);
1586                             }
1587                             // free frame
1588                             if (pp_frame != NULL) {
1589                                 pme->releaseSuperBuf(pp_frame);
1590                                 free(pp_frame);
1591                             }
1592                             //free metadata
1593                             if (NULL != meta_buffer) {
1594                                 pme->m_parent->metadataBufDone(meta_buffer);
1595                                 free(meta_buffer);
1596                             }
1597                         }
1598                     } else {
1599                         pthread_mutex_unlock(&pme->mReprocJobLock);
1600                     }
1601                 } else {
1602                     // not active, simply return buf and do no op
1603                     qcamera_hal3_jpeg_data_t *jpeg_job =
1604                         (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1605                     if (NULL != jpeg_job) {
1606                         free(jpeg_job);
1607                     }
1608                     mm_camera_super_buf_t *super_buf;
1609                     super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
1610                     if (NULL != super_buf) {
1611                         pme->releaseSuperBuf(super_buf);
1612                         free(super_buf);
1613                     }
1614                     super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
1615                     if (NULL != super_buf) {
1616                         pme->releaseSuperBuf(super_buf);
1617                         free(super_buf);
1618                     }
1619                     mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
1620                     if (metadata != NULL) {
1621                         pme->m_parent->metadataBufDone(metadata);
1622                         free(metadata);
1623                     }
1624                     qcamera_fwk_input_pp_data_t *fwk_frame =
1625                             (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
1626                     if (NULL != fwk_frame) {
1627                         free(fwk_frame);
1628                     }
1629                 }
1630             }
1631             break;
1632         case CAMERA_CMD_TYPE_EXIT:
1633             running = 0;
1634             break;
1635         default:
1636             break;
1637         }
1638     } while (running);
1639     CDBG("%s: X", __func__);
1640     return NULL;
1641 }
1642 
1643 /*===========================================================================
1644  * FUNCTION   : QCamera3Exif
1645  *
1646  * DESCRIPTION: constructor of QCamera3Exif
1647  *
1648  * PARAMETERS : None
1649  *
1650  * RETURN     : None
1651  *==========================================================================*/
QCamera3Exif()1652 QCamera3Exif::QCamera3Exif()
1653     : m_nNumEntries(0)
1654 {
1655     memset(m_Entries, 0, sizeof(m_Entries));
1656 }
1657 
1658 /*===========================================================================
1659  * FUNCTION   : ~QCamera3Exif
1660  *
1661  * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
1662  *
1663  * PARAMETERS : None
1664  *
1665  * RETURN     : None
1666  *==========================================================================*/
~QCamera3Exif()1667 QCamera3Exif::~QCamera3Exif()
1668 {
1669     for (uint32_t i = 0; i < m_nNumEntries; i++) {
1670         switch (m_Entries[i].tag_entry.type) {
1671             case EXIF_BYTE:
1672                 {
1673                     if (m_Entries[i].tag_entry.count > 1 &&
1674                             m_Entries[i].tag_entry.data._bytes != NULL) {
1675                         free(m_Entries[i].tag_entry.data._bytes);
1676                         m_Entries[i].tag_entry.data._bytes = NULL;
1677                     }
1678                 }
1679                 break;
1680             case EXIF_ASCII:
1681                 {
1682                     if (m_Entries[i].tag_entry.data._ascii != NULL) {
1683                         free(m_Entries[i].tag_entry.data._ascii);
1684                         m_Entries[i].tag_entry.data._ascii = NULL;
1685                     }
1686                 }
1687                 break;
1688             case EXIF_SHORT:
1689                 {
1690                     if (m_Entries[i].tag_entry.count > 1 &&
1691                             m_Entries[i].tag_entry.data._shorts != NULL) {
1692                         free(m_Entries[i].tag_entry.data._shorts);
1693                         m_Entries[i].tag_entry.data._shorts = NULL;
1694                     }
1695                 }
1696                 break;
1697             case EXIF_LONG:
1698                 {
1699                     if (m_Entries[i].tag_entry.count > 1 &&
1700                             m_Entries[i].tag_entry.data._longs != NULL) {
1701                         free(m_Entries[i].tag_entry.data._longs);
1702                         m_Entries[i].tag_entry.data._longs = NULL;
1703                     }
1704                 }
1705                 break;
1706             case EXIF_RATIONAL:
1707                 {
1708                     if (m_Entries[i].tag_entry.count > 1 &&
1709                             m_Entries[i].tag_entry.data._rats != NULL) {
1710                         free(m_Entries[i].tag_entry.data._rats);
1711                         m_Entries[i].tag_entry.data._rats = NULL;
1712                     }
1713                 }
1714                 break;
1715             case EXIF_UNDEFINED:
1716                 {
1717                     if (m_Entries[i].tag_entry.data._undefined != NULL) {
1718                         free(m_Entries[i].tag_entry.data._undefined);
1719                         m_Entries[i].tag_entry.data._undefined = NULL;
1720                     }
1721                 }
1722                 break;
1723             case EXIF_SLONG:
1724                 {
1725                     if (m_Entries[i].tag_entry.count > 1 &&
1726                             m_Entries[i].tag_entry.data._slongs != NULL) {
1727                         free(m_Entries[i].tag_entry.data._slongs);
1728                         m_Entries[i].tag_entry.data._slongs = NULL;
1729                     }
1730                 }
1731                 break;
1732             case EXIF_SRATIONAL:
1733                 {
1734                     if (m_Entries[i].tag_entry.count > 1 &&
1735                             m_Entries[i].tag_entry.data._srats != NULL) {
1736                         free(m_Entries[i].tag_entry.data._srats);
1737                         m_Entries[i].tag_entry.data._srats = NULL;
1738                     }
1739                 }
1740                 break;
1741             default:
1742                 ALOGE("%s: Error, Unknown type",__func__);
1743                 break;
1744         }
1745     }
1746 }
1747 
1748 /*===========================================================================
1749  * FUNCTION   : addEntry
1750  *
1751  * DESCRIPTION: function to add an entry to exif data
1752  *
1753  * PARAMETERS :
1754  *   @tagid   : exif tag ID
1755  *   @type    : data type
1756  *   @count   : number of data in uint of its type
1757  *   @data    : input data ptr
1758  *
1759  * RETURN     : int32_t type of status
1760  *              NO_ERROR  -- success
1761  *              none-zero failure code
1762  *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)1763 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
1764                               exif_tag_type_t type,
1765                               uint32_t count,
1766                               void *data)
1767 {
1768     int32_t rc = NO_ERROR;
1769     if(m_nNumEntries >= MAX_HAL3_EXIF_TABLE_ENTRIES) {
1770         ALOGE("%s: Number of entries exceeded limit", __func__);
1771         return NO_MEMORY;
1772     }
1773 
1774     m_Entries[m_nNumEntries].tag_id = tagid;
1775     m_Entries[m_nNumEntries].tag_entry.type = type;
1776     m_Entries[m_nNumEntries].tag_entry.count = count;
1777     m_Entries[m_nNumEntries].tag_entry.copy = 1;
1778     switch (type) {
1779         case EXIF_BYTE:
1780             {
1781                 if (count > 1) {
1782                     uint8_t *values = (uint8_t *)malloc(count);
1783                     if (values == NULL) {
1784                         ALOGE("%s: No memory for byte array", __func__);
1785                         rc = NO_MEMORY;
1786                     } else {
1787                         memcpy(values, data, count);
1788                         m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
1789                     }
1790                 } else {
1791                     m_Entries[m_nNumEntries].tag_entry.data._byte =
1792                         *(uint8_t *)data;
1793                 }
1794             }
1795             break;
1796         case EXIF_ASCII:
1797             {
1798                 char *str = NULL;
1799                 str = (char *)malloc(count + 1);
1800                 if (str == NULL) {
1801                     ALOGE("%s: No memory for ascii string", __func__);
1802                     rc = NO_MEMORY;
1803                 } else {
1804                     memset(str, 0, count + 1);
1805                     memcpy(str, data, count);
1806                     m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
1807                 }
1808             }
1809             break;
1810         case EXIF_SHORT:
1811             {
1812                 if (count > 1) {
1813                     uint16_t *values =
1814                         (uint16_t *)malloc(count * sizeof(uint16_t));
1815                     if (values == NULL) {
1816                         ALOGE("%s: No memory for short array", __func__);
1817                         rc = NO_MEMORY;
1818                     } else {
1819                         memcpy(values, data, count * sizeof(uint16_t));
1820                         m_Entries[m_nNumEntries].tag_entry.data._shorts =values;
1821                     }
1822                 } else {
1823                     m_Entries[m_nNumEntries].tag_entry.data._short =
1824                         *(uint16_t *)data;
1825                 }
1826             }
1827             break;
1828         case EXIF_LONG:
1829             {
1830                 if (count > 1) {
1831                     uint32_t *values =
1832                         (uint32_t *)malloc(count * sizeof(uint32_t));
1833                     if (values == NULL) {
1834                         ALOGE("%s: No memory for long array", __func__);
1835                         rc = NO_MEMORY;
1836                     } else {
1837                         memcpy(values, data, count * sizeof(uint32_t));
1838                         m_Entries[m_nNumEntries].tag_entry.data._longs = values;
1839                     }
1840                 } else {
1841                     m_Entries[m_nNumEntries].tag_entry.data._long =
1842                         *(uint32_t *)data;
1843                 }
1844             }
1845             break;
1846         case EXIF_RATIONAL:
1847             {
1848                 if (count > 1) {
1849                     rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
1850                     if (values == NULL) {
1851                         ALOGE("%s: No memory for rational array", __func__);
1852                         rc = NO_MEMORY;
1853                     } else {
1854                         memcpy(values, data, count * sizeof(rat_t));
1855                         m_Entries[m_nNumEntries].tag_entry.data._rats = values;
1856                     }
1857                 } else {
1858                     m_Entries[m_nNumEntries].tag_entry.data._rat =
1859                         *(rat_t *)data;
1860                 }
1861             }
1862             break;
1863         case EXIF_UNDEFINED:
1864             {
1865                 uint8_t *values = (uint8_t *)malloc(count);
1866                 if (values == NULL) {
1867                     ALOGE("%s: No memory for undefined array", __func__);
1868                     rc = NO_MEMORY;
1869                 } else {
1870                     memcpy(values, data, count);
1871                     m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
1872                 }
1873             }
1874             break;
1875         case EXIF_SLONG:
1876             {
1877                 if (count > 1) {
1878                     int32_t *values =
1879                         (int32_t *)malloc(count * sizeof(int32_t));
1880                     if (values == NULL) {
1881                         ALOGE("%s: No memory for signed long array", __func__);
1882                         rc = NO_MEMORY;
1883                     } else {
1884                         memcpy(values, data, count * sizeof(int32_t));
1885                         m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
1886                     }
1887                 } else {
1888                     m_Entries[m_nNumEntries].tag_entry.data._slong =
1889                         *(int32_t *)data;
1890                 }
1891             }
1892             break;
1893         case EXIF_SRATIONAL:
1894             {
1895                 if (count > 1) {
1896                     srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
1897                     if (values == NULL) {
1898                         ALOGE("%s: No memory for sign rational array",__func__);
1899                         rc = NO_MEMORY;
1900                     } else {
1901                         memcpy(values, data, count * sizeof(srat_t));
1902                         m_Entries[m_nNumEntries].tag_entry.data._srats = values;
1903                     }
1904                 } else {
1905                     m_Entries[m_nNumEntries].tag_entry.data._srat =
1906                         *(srat_t *)data;
1907                 }
1908             }
1909             break;
1910         default:
1911             ALOGE("%s: Error, Unknown type",__func__);
1912             break;
1913     }
1914 
1915     // Increase number of entries
1916     m_nNumEntries++;
1917     return rc;
1918 }
1919 
1920 }; // namespace qcamera
1921