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