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 
30 #define LOG_TAG "QCamera3PostProc"
31 //#define LOG_NDEBUG 0
32 
33 #include <stdlib.h>
34 #include <utils/Errors.h>
35 
36 #include "QCamera3PostProc.h"
37 #include "QCamera3HWI.h"
38 #include "QCamera3Channel.h"
39 #include "QCamera3Stream.h"
40 
41 namespace qcamera {
42 
43 /*===========================================================================
44  * FUNCTION   : QCamera3PostProcessor
45  *
46  * DESCRIPTION: constructor of QCamera3PostProcessor.
47  *
48  * PARAMETERS :
49  *   @cam_ctrl : ptr to HWI object
50  *
51  * RETURN     : None
52  *==========================================================================*/
QCamera3PostProcessor(QCamera3PicChannel * ch_ctrl)53 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3PicChannel* ch_ctrl)
54     : m_parent(ch_ctrl),
55       mJpegCB(NULL),
56       mJpegUserData(NULL),
57       mJpegClientHandle(0),
58       mJpegSessionId(0),
59       m_pJpegExifObj(NULL),
60       m_bThumbnailNeeded(TRUE),
61       m_pReprocChannel(NULL),
62       m_inputPPQ(releasePPInputData, this),
63       m_ongoingPPQ(releaseOngoingPPData, this),
64       m_inputJpegQ(releaseJpegData, this),
65       m_ongoingJpegQ(releaseJpegData, this),
66       m_inputRawQ(releasePPInputData, this),
67       m_inputMetaQ(releaseMetaData, this),
68       m_jpegSettingsQ(releaseJpegSetting, this)
69 {
70     memset(&mJpegHandle, 0, sizeof(mJpegHandle));
71     pthread_mutex_init(&mReprocJobLock, NULL);
72 }
73 
74 /*===========================================================================
75  * FUNCTION   : ~QCamera3PostProcessor
76  *
77  * DESCRIPTION: deconstructor of QCamera3PostProcessor.
78  *
79  * PARAMETERS : None
80  *
81  * RETURN     : None
82  *==========================================================================*/
~QCamera3PostProcessor()83 QCamera3PostProcessor::~QCamera3PostProcessor()
84 {
85     if (m_pJpegExifObj != NULL) {
86         delete m_pJpegExifObj;
87         m_pJpegExifObj = NULL;
88     }
89     pthread_mutex_destroy(&mReprocJobLock);
90 }
91 
92 /*===========================================================================
93  * FUNCTION   : init
94  *
95  * DESCRIPTION: initialization of postprocessor
96  *
97  * PARAMETERS :
98  *   @jpeg_cb      : callback to handle jpeg event from mm-camera-interface
99  *   @user_data    : user data ptr for jpeg callback
100  *
101  * RETURN     : int32_t type of status
102  *              NO_ERROR  -- success
103  *              none-zero failure code
104  *==========================================================================*/
init(QCamera3Memory * mMemory,jpeg_encode_callback_t jpeg_cb,void * user_data)105 int32_t QCamera3PostProcessor::init(QCamera3Memory* mMemory,
106                                     jpeg_encode_callback_t jpeg_cb, void *user_data)
107 {
108     mJpegCB = jpeg_cb;
109     mJpegUserData = user_data;
110     mJpegMem = mMemory;
111     mJpegClientHandle = jpeg_open(&mJpegHandle);
112     if(!mJpegClientHandle) {
113         ALOGE("%s : jpeg_open did not work", __func__);
114         return UNKNOWN_ERROR;
115     }
116 
117     m_dataProcTh.launch(dataProcessRoutine, this);
118 
119     return NO_ERROR;
120 }
121 
122 /*===========================================================================
123  * FUNCTION   : deinit
124  *
125  * DESCRIPTION: de-initialization of postprocessor
126  *
127  * PARAMETERS : None
128  *
129  * RETURN     : int32_t type of status
130  *              NO_ERROR  -- success
131  *              none-zero failure code
132  *==========================================================================*/
deinit()133 int32_t QCamera3PostProcessor::deinit()
134 {
135     m_dataProcTh.exit();
136 
137     if (m_pReprocChannel != NULL) {
138         m_pReprocChannel->stop();
139         delete m_pReprocChannel;
140         m_pReprocChannel = NULL;
141     }
142 
143     if(mJpegClientHandle > 0) {
144         int rc = mJpegHandle.close(mJpegClientHandle);
145         ALOGD("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
146               __func__, rc, mJpegClientHandle);
147         mJpegClientHandle = 0;
148         memset(&mJpegHandle, 0, sizeof(mJpegHandle));
149     }
150 
151     mJpegMem = NULL;
152 
153     return NO_ERROR;
154 }
155 
156 /*===========================================================================
157  * FUNCTION   : start
158  *
159  * DESCRIPTION: start postprocessor. Data process thread and data notify thread
160  *              will be launched.
161  *
162  * PARAMETERS :
163  *   @pMemory       : memory object representing buffers to store JPEG.
164  *   @pInputChannel : Input channel obj ptr that possibly needs reprocess
165  *   @metadata      : metadata for the reprocessing
166  *
167  * RETURN     : int32_t type of status
168  *              NO_ERROR  -- success
169  *              none-zero failure code
170  *
171  * NOTE       : if any reprocess is needed, a reprocess channel/stream
172  *              will be started.
173  *==========================================================================*/
start(QCamera3Channel * pInputChannel,metadata_buffer_t * metadata)174 int32_t QCamera3PostProcessor::start(QCamera3Channel *pInputChannel,
175                                      metadata_buffer_t *metadata)
176 {
177     int32_t rc = NO_ERROR;
178     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
179 
180     if (hal_obj->needReprocess()) {
181 
182         while (!m_inputMetaQ.isEmpty()) {
183            m_pReprocChannel->metadataBufDone((mm_camera_super_buf_t *)m_inputMetaQ.dequeue());
184         }
185         if (m_pReprocChannel != NULL) {
186             m_pReprocChannel->stop();
187             delete m_pReprocChannel;
188             m_pReprocChannel = NULL;
189         }
190 
191         // if reprocess is needed, start reprocess channel
192         QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
193         ALOGV("%s: Setting input channel as pInputChannel", __func__);
194         m_pReprocChannel = hal_obj->addOfflineReprocChannel(pInputChannel, m_parent, metadata);
195         if (m_pReprocChannel == NULL) {
196             ALOGE("%s: cannot add reprocess channel", __func__);
197             return UNKNOWN_ERROR;
198         }
199 
200         rc = m_pReprocChannel->start();
201         if (rc != 0) {
202             ALOGE("%s: cannot start reprocess channel", __func__);
203             delete m_pReprocChannel;
204             m_pReprocChannel = NULL;
205             return rc;
206         }
207     }
208     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE);
209 
210     return rc;
211 }
212 
213 /*===========================================================================
214  * FUNCTION   : stop
215  *
216  * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
217  *
218  * PARAMETERS : None
219  *
220  * RETURN     : int32_t type of status
221  *              NO_ERROR  -- success
222  *              none-zero failure code
223  *
224  * NOTE       : reprocess channel will be stopped and deleted if there is any
225  *==========================================================================*/
stop()226 int32_t QCamera3PostProcessor::stop()
227 {
228     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
229 
230     if (m_pReprocChannel != NULL) {
231         m_pReprocChannel->stop();
232         delete m_pReprocChannel;
233         m_pReprocChannel = NULL;
234     }
235 
236     return NO_ERROR;
237 }
238 
239 /*===========================================================================
240  * FUNCTION   : getJpegEncodeConfig
241  *
242  * DESCRIPTION: function to prepare encoding job information
243  *
244  * PARAMETERS :
245  *   @encode_parm   : param to be filled with encoding configuration
246  *   #main_stream   : stream object where the input buffer comes from
247  *   @jpeg_settings : jpeg settings to be applied for encoding
248  *
249  * RETURN     : int32_t type of status
250  *              NO_ERROR  -- success
251  *              none-zero failure code
252  *==========================================================================*/
getJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,QCamera3Stream * main_stream,jpeg_settings_t * jpeg_settings)253 int32_t QCamera3PostProcessor::getJpegEncodeConfig(
254                 mm_jpeg_encode_params_t& encode_parm,
255                 QCamera3Stream *main_stream,
256                 jpeg_settings_t *jpeg_settings)
257 {
258     ALOGV("%s : E", __func__);
259     int32_t ret = NO_ERROR;
260 
261     encode_parm.jpeg_cb = mJpegCB;
262     encode_parm.userdata = mJpegUserData;
263 
264     if (jpeg_settings->thumbnail_size.width > 0 &&
265             jpeg_settings->thumbnail_size.height > 0)
266         m_bThumbnailNeeded = TRUE;
267     else
268         m_bThumbnailNeeded = FALSE;
269     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
270 
271     // get color format
272     cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12;  //default value
273     main_stream->getFormat(img_fmt);
274     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
275 
276     // get jpeg quality
277     encode_parm.quality = jpeg_settings->jpeg_quality;
278 
279     // get jpeg thumbnail quality
280     encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
281 
282     cam_frame_len_offset_t main_offset;
283     memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
284     main_stream->getFrameOffset(main_offset);
285 
286     // src buf config
287     //Pass input main image buffer info to encoder.
288     QCamera3Memory *pStreamMem = main_stream->getStreamBufs();
289     if (pStreamMem == NULL) {
290         ALOGE("%s: cannot get stream bufs from main stream", __func__);
291         ret = BAD_VALUE;
292         goto on_error;
293     }
294     encode_parm.num_src_bufs = pStreamMem->getCnt();
295     for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
296         if (pStreamMem != NULL) {
297             encode_parm.src_main_buf[i].index = i;
298             encode_parm.src_main_buf[i].buf_size = pStreamMem->getSize(i);
299             encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
300             encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
301             encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
302             encode_parm.src_main_buf[i].offset = main_offset;
303         }
304     }
305 
306     //Pass input thumbnail buffer info to encoder.
307     //Note: In this version thumb_stream = main_stream
308     if (m_bThumbnailNeeded == TRUE) {
309         pStreamMem = main_stream->getStreamBufs();
310         if (pStreamMem == NULL) {
311             ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
312             ret = BAD_VALUE;
313             goto on_error;
314         }
315         cam_frame_len_offset_t thumb_offset;
316         memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
317         main_stream->getFrameOffset(thumb_offset);
318         encode_parm.num_tmb_bufs = pStreamMem->getCnt();
319         for (int i = 0; i < pStreamMem->getCnt(); i++) {
320             if (pStreamMem != NULL) {
321                 encode_parm.src_thumb_buf[i].index = i;
322                 encode_parm.src_thumb_buf[i].buf_size = pStreamMem->getSize(i);
323                 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
324                 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
325                 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
326                 encode_parm.src_thumb_buf[i].offset = thumb_offset;
327             }
328         }
329     }
330 
331     //Pass output jpeg buffer info to encoder.
332     //mJpegMem is allocated by framework.
333     encode_parm.num_dst_bufs = 1;
334     encode_parm.dest_buf[0].index = 0;
335     encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(
336             jpeg_settings->out_buf_index);
337     encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(
338             jpeg_settings->out_buf_index);
339     encode_parm.dest_buf[0].fd = mJpegMem->getFd(
340             jpeg_settings->out_buf_index);
341     encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
342     encode_parm.dest_buf[0].offset = main_offset;
343 
344     ALOGV("%s : X", __func__);
345     return NO_ERROR;
346 
347 on_error:
348 
349     ALOGV("%s : X with error %d", __func__, ret);
350     return ret;
351 }
352 
353 /*===========================================================================
354  * FUNCTION   : processData
355  *
356  * DESCRIPTION: enqueue data into dataProc thread
357  *
358  * PARAMETERS :
359  *   @frame   : process frame received from mm-camera-interface
360  *
361  * RETURN     : int32_t type of status
362  *              NO_ERROR  -- success
363  *              none-zero failure code
364  *
365  * NOTE       : depends on if offline reprocess is needed, received frame will
366  *              be sent to either input queue of postprocess or jpeg encoding
367  *==========================================================================*/
processData(mm_camera_super_buf_t * frame)368 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame)
369 {
370     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
371     if (hal_obj->needReprocess()) {
372         pthread_mutex_lock(&mReprocJobLock);
373         // enqueu to post proc input queue
374         m_inputPPQ.enqueue((void *)frame);
375         if (!(m_inputMetaQ.isEmpty())) {
376            ALOGV("%s: meta queue is not empty, do next job", __func__);
377            m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
378         }
379         pthread_mutex_unlock(&mReprocJobLock);
380     } else {
381         ALOGD("%s: no need offline reprocess, sending to jpeg encoding", __func__);
382         qcamera_jpeg_data_t *jpeg_job =
383             (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
384         if (jpeg_job == NULL) {
385             ALOGE("%s: No memory for jpeg job", __func__);
386             return NO_MEMORY;
387         }
388 
389         memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
390         jpeg_job->src_frame = frame;
391 
392         // enqueu to jpeg input queue
393         m_inputJpegQ.enqueue((void *)jpeg_job);
394         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
395     }
396 
397     return NO_ERROR;
398 }
399 
400 /*===========================================================================
401  * FUNCTION   : processPPMetadata
402  *
403  * DESCRIPTION: enqueue data into dataProc thread
404  *
405  * PARAMETERS :
406  *   @frame   : process metadata frame received from pic channel
407  *
408  * RETURN     : int32_t type of status
409  *              NO_ERROR  -- success
410  *              none-zero failure code
411  *
412  *==========================================================================*/
processPPMetadata(metadata_buffer_t * reproc_meta)413 int32_t QCamera3PostProcessor::processPPMetadata(metadata_buffer_t *reproc_meta)
414 {
415    pthread_mutex_lock(&mReprocJobLock);
416     // enqueue to metadata input queue
417     m_inputMetaQ.enqueue((void *)reproc_meta);
418     if (!(m_inputPPQ.isEmpty())) {
419        ALOGI("%s: pp queue is not empty, do next job", __func__);
420        m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
421     } else {
422        ALOGI("%s: pp queue is empty, not calling do next job", __func__);
423     }
424     pthread_mutex_unlock(&mReprocJobLock);
425     return NO_ERROR;
426 }
427 
428 /*===========================================================================
429  * FUNCTION   : processJpegSettingData
430  *
431  * DESCRIPTION: enqueue jpegSetting into dataProc thread
432  *
433  * PARAMETERS :
434  *   @jpeg_settings : jpeg settings data received from pic channel
435  *
436  * RETURN     : int32_t type of status
437  *              NO_ERROR  -- success
438  *              none-zero failure code
439  *
440  *==========================================================================*/
processJpegSettingData(jpeg_settings_t * jpeg_settings)441 int32_t QCamera3PostProcessor::processJpegSettingData(
442         jpeg_settings_t *jpeg_settings)
443 {
444     if (!jpeg_settings) {
445         ALOGE("%s: invalid jpeg settings pointer", __func__);
446         return -EINVAL;
447     }
448     return m_jpegSettingsQ.enqueue((void *)jpeg_settings);
449 }
450 
451 /*===========================================================================
452  * FUNCTION   : processRawData
453  *
454  * DESCRIPTION: enqueue raw data into dataProc thread
455  *
456  * PARAMETERS :
457  *   @frame   : process frame received from mm-camera-interface
458  *
459  * RETURN     : int32_t type of status
460  *              NO_ERROR  -- success
461  *              none-zero failure code
462  *==========================================================================*/
processRawData(mm_camera_super_buf_t * frame)463 int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame)
464 {
465     // enqueu to raw input queue
466     m_inputRawQ.enqueue((void *)frame);
467     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
468     return NO_ERROR;
469 }
470 
471 /*===========================================================================
472  * FUNCTION   : processPPData
473  *
474  * DESCRIPTION: process received frame after reprocess.
475  *
476  * PARAMETERS :
477  *   @frame   : received frame from reprocess channel.
478  *
479  * RETURN     : int32_t type of status
480  *              NO_ERROR  -- success
481  *              none-zero failure code
482  *
483  * NOTE       : The frame after reprocess need to send to jpeg encoding.
484  *==========================================================================*/
processPPData(mm_camera_super_buf_t * frame)485 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame)
486 {
487     qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue();
488     jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue();
489 
490     if (job == NULL || job->src_frame == NULL) {
491         ALOGE("%s: Cannot find reprocess job", __func__);
492         return BAD_VALUE;
493     }
494     if (jpeg_settings == NULL) {
495         ALOGE("%s: Cannot find jpeg settings", __func__);
496         return BAD_VALUE;
497     }
498 
499     qcamera_jpeg_data_t *jpeg_job =
500         (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
501     if (jpeg_job == NULL) {
502         ALOGE("%s: No memory for jpeg job", __func__);
503         return NO_MEMORY;
504     }
505 
506     memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
507     jpeg_job->src_frame = frame;
508     jpeg_job->src_reproc_frame = job->src_frame;
509     jpeg_job->metadata = job->metadata;
510     jpeg_job->jpeg_settings = jpeg_settings;
511 
512     // free pp job buf
513     free(job);
514 
515     // enqueu reprocessed frame to jpeg input queue
516     m_inputJpegQ.enqueue((void *)jpeg_job);
517 
518     // wait up data proc thread
519     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
520 
521     return NO_ERROR;
522 }
523 
524 /*===========================================================================
525  * FUNCTION   : findJpegJobByJobId
526  *
527  * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
528  *
529  * PARAMETERS :
530  *   @jobId   : job Id of the job
531  *
532  * RETURN     : ptr to a jpeg job struct. NULL if not found.
533  *
534  * NOTE       : Currently only one job is sending to mm-jpeg-interface for jpeg
535  *              encoding. Therefore simply dequeue from the ongoing Jpeg Queue
536  *              will serve the purpose to find the jpeg job.
537  *==========================================================================*/
findJpegJobByJobId(uint32_t jobId)538 qcamera_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId)
539 {
540     qcamera_jpeg_data_t * job = NULL;
541     if (jobId == 0) {
542         ALOGE("%s: not a valid jpeg jobId", __func__);
543         return NULL;
544     }
545 
546     // currely only one jpeg job ongoing, so simply dequeue the head
547     job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue();
548     return job;
549 }
550 
551 /*===========================================================================
552  * FUNCTION   : releasePPInputData
553  *
554  * DESCRIPTION: callback function to release post process input data node
555  *
556  * PARAMETERS :
557  *   @data      : ptr to post process input data
558  *   @user_data : user data ptr (QCamera3Reprocessor)
559  *
560  * RETURN     : None
561  *==========================================================================*/
releasePPInputData(void * data,void * user_data)562 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data)
563 {
564     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
565     if (NULL != pme) {
566         pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
567     }
568 }
569 
570 /*===========================================================================
571  * FUNCTION   : releaseMetaData
572  *
573  * DESCRIPTION: callback function to release meta data node
574  *
575  * PARAMETERS :
576  *   @data      : ptr to post process input data
577  *   @user_data : user data ptr (QCamera3Reprocessor)
578  *
579  * RETURN     : None
580  *==========================================================================*/
releaseMetaData(void * data,void *)581 void QCamera3PostProcessor::releaseMetaData(void *data, void * /*user_data*/)
582 {
583     metadata_buffer_t *metadata = (metadata_buffer_t *)data;
584     if (metadata != NULL)
585         free(metadata);
586 }
587 
588 /*===========================================================================
589  * FUNCTION   : releaseJpegSetting
590  *
591  * DESCRIPTION: callback function to release meta data node
592  *
593  * PARAMETERS :
594  *   @data      : ptr to post process input data
595  *   @user_data : user data ptr (QCamera3Reprocessor)
596  *
597  * RETURN     : None
598  *==========================================================================*/
releaseJpegSetting(void * data,void *)599 void QCamera3PostProcessor::releaseJpegSetting(void *data, void * /*user_data*/)
600 {
601     jpeg_settings_t *jpegSetting = (jpeg_settings_t *)data;
602     if (jpegSetting != NULL)
603         free(jpegSetting);
604 }
605 
606 /*===========================================================================
607  * FUNCTION   : releaseJpegData
608  *
609  * DESCRIPTION: callback function to release jpeg job node
610  *
611  * PARAMETERS :
612  *   @data      : ptr to ongoing jpeg job data
613  *   @user_data : user data ptr (QCamera3Reprocessor)
614  *
615  * RETURN     : None
616  *==========================================================================*/
releaseJpegData(void * data,void * user_data)617 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data)
618 {
619     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
620     if (NULL != pme) {
621         pme->releaseJpegJobData((qcamera_jpeg_data_t *)data);
622     }
623 }
624 
625 /*===========================================================================
626  * FUNCTION   : releaseOngoingPPData
627  *
628  * DESCRIPTION: callback function to release ongoing postprocess job node
629  *
630  * PARAMETERS :
631  *   @data      : ptr to onging postprocess job
632  *   @user_data : user data ptr (QCamera3Reprocessor)
633  *
634  * RETURN     : None
635  *==========================================================================*/
releaseOngoingPPData(void * data,void * user_data)636 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data)
637 {
638     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
639     if (NULL != pme) {
640         qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data;
641         if (NULL != pp_job->src_frame) {
642             pme->releaseSuperBuf(pp_job->src_frame);
643             free(pp_job->src_frame);
644             free(pp_job->metadata);
645             pp_job->src_frame = NULL;
646             pp_job->metadata = NULL;
647         }
648     }
649 }
650 
651 /*===========================================================================
652  * FUNCTION   : releaseSuperBuf
653  *
654  * DESCRIPTION: function to release a superbuf frame by returning back to kernel
655  *
656  * PARAMETERS :
657  *   @super_buf : ptr to the superbuf frame
658  *
659  * RETURN     : None
660  *==========================================================================*/
releaseSuperBuf(mm_camera_super_buf_t * super_buf)661 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
662 {
663     if (NULL != super_buf) {
664         if (m_parent != NULL) {
665             m_parent->bufDone(super_buf);
666         }
667     }
668 }
669 
670 /*===========================================================================
671  * FUNCTION   : releaseJpegJobData
672  *
673  * DESCRIPTION: function to release internal resources in jpeg job struct
674  *
675  * PARAMETERS :
676  *   @job     : ptr to jpeg job struct
677  *
678  * RETURN     : None
679  *
680  * NOTE       : original source frame need to be queued back to kernel for
681  *              future use. Output buf of jpeg job need to be released since
682  *              it's allocated for each job. Exif object need to be deleted.
683  *==========================================================================*/
releaseJpegJobData(qcamera_jpeg_data_t * job)684 void QCamera3PostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job)
685 {
686     ALOGV("%s: E", __func__);
687     if (NULL != job) {
688         if (NULL != job->src_reproc_frame) {
689             free(job->src_reproc_frame);
690             job->src_reproc_frame = NULL;
691         }
692 
693         if (NULL != job->src_frame) {
694             free(job->src_frame);
695             job->src_frame = NULL;
696         }
697 
698         if (NULL != job->metadata) {
699             free(job->metadata);
700             job->metadata = NULL;
701         }
702 
703         if (NULL != job->jpeg_settings) {
704             free(job->jpeg_settings);
705             job->jpeg_settings = NULL;
706         }
707     }
708     ALOGV("%s: X", __func__);
709 }
710 
711 /*===========================================================================
712  * FUNCTION   : getColorfmtFromImgFmt
713  *
714  * DESCRIPTION: function to return jpeg color format based on its image format
715  *
716  * PARAMETERS :
717  *   @img_fmt : image format
718  *
719  * RETURN     : jpeg color format that can be understandable by omx lib
720  *==========================================================================*/
getColorfmtFromImgFmt(cam_format_t img_fmt)721 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
722 {
723     switch (img_fmt) {
724     case CAM_FORMAT_YUV_420_NV21:
725         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
726     case CAM_FORMAT_YUV_420_NV21_ADRENO:
727         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
728     case CAM_FORMAT_YUV_420_NV12:
729         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
730     case CAM_FORMAT_YUV_420_YV12:
731         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
732     case CAM_FORMAT_YUV_422_NV61:
733         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
734     case CAM_FORMAT_YUV_422_NV16:
735         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
736     default:
737         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
738     }
739 }
740 
741 /*===========================================================================
742  * FUNCTION   : getJpegImgTypeFromImgFmt
743  *
744  * DESCRIPTION: function to return jpeg encode image type based on its image format
745  *
746  * PARAMETERS :
747  *   @img_fmt : image format
748  *
749  * RETURN     : return jpeg source image format (YUV or Bitstream)
750  *==========================================================================*/
getJpegImgTypeFromImgFmt(cam_format_t img_fmt)751 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
752 {
753     switch (img_fmt) {
754     case CAM_FORMAT_YUV_420_NV21:
755     case CAM_FORMAT_YUV_420_NV21_ADRENO:
756     case CAM_FORMAT_YUV_420_NV12:
757     case CAM_FORMAT_YUV_420_YV12:
758     case CAM_FORMAT_YUV_422_NV61:
759     case CAM_FORMAT_YUV_422_NV16:
760         return MM_JPEG_FMT_YUV;
761     default:
762         return MM_JPEG_FMT_YUV;
763     }
764 }
765 
766 /*===========================================================================
767  * FUNCTION   : encodeData
768  *
769  * DESCRIPTION: function to prepare encoding job information and send to
770  *              mm-jpeg-interface to do the encoding job
771  *
772  * PARAMETERS :
773  *   @jpeg_job_data : ptr to a struct saving job related information
774  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
775  *                    to be created. After creation, this flag will be toggled
776  *
777  * RETURN     : int32_t type of status
778  *              NO_ERROR  -- success
779  *              none-zero failure code
780  *==========================================================================*/
encodeData(qcamera_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)781 int32_t QCamera3PostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data,
782                           uint8_t &needNewSess)
783 {
784     ALOGV("%s : E", __func__);
785     int32_t ret = NO_ERROR;
786     mm_jpeg_job_t jpg_job;
787     uint32_t jobId = 0;
788     QCamera3Stream *main_stream = NULL;
789     mm_camera_buf_def_t *main_frame = NULL;
790     QCamera3Stream *thumb_stream = NULL;
791     mm_camera_buf_def_t *thumb_frame = NULL;
792     QCamera3Channel *srcChannel = NULL;
793     mm_camera_super_buf_t *recvd_frame = NULL;
794     metadata_buffer_t *metadata = NULL;
795     jpeg_settings_t *jpeg_settings = NULL;
796     QCamera3HardwareInterface* hal_obj = NULL;
797 
798 
799     hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
800     recvd_frame = jpeg_job_data->src_frame;
801     metadata = jpeg_job_data->metadata;
802     jpeg_settings = jpeg_job_data->jpeg_settings;
803 
804     QCamera3Channel *pChannel = NULL;
805     // first check picture channel
806     if (m_parent != NULL &&
807         m_parent->getMyHandle() == recvd_frame->ch_id) {
808         pChannel = m_parent;
809     }
810     // check reprocess channel if not found
811     if (pChannel == NULL) {
812         if (m_pReprocChannel != NULL &&
813             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
814             pChannel = m_pReprocChannel;
815         }
816     }
817 
818     srcChannel = pChannel;
819 
820     if (srcChannel == NULL) {
821         ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here",
822               __func__, recvd_frame->ch_id);
823         return BAD_VALUE;
824     }
825 
826     // find snapshot frame and thumnail frame
827     //Note: In this version we will receive only snapshot frame.
828     for (int i = 0; i < recvd_frame->num_bufs; i++) {
829         QCamera3Stream *srcStream =
830             srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
831         if (srcStream != NULL) {
832             switch (srcStream->getMyType()) {
833             case CAM_STREAM_TYPE_SNAPSHOT:
834             case CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT:
835             case CAM_STREAM_TYPE_OFFLINE_PROC:
836                 main_stream = srcStream;
837                 main_frame = recvd_frame->bufs[i];
838                 break;
839             case CAM_STREAM_TYPE_PREVIEW:
840             case CAM_STREAM_TYPE_POSTVIEW:
841                 thumb_stream = srcStream;
842                 thumb_frame = recvd_frame->bufs[i];
843                 break;
844             default:
845                 break;
846             }
847         }
848     }
849 
850     if(NULL == main_frame){
851        ALOGE("%s : Main frame is NULL", __func__);
852        return BAD_VALUE;
853     }
854 
855     QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info;
856     if (NULL == memObj) {
857         ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
858         return NO_MEMORY;
859     }
860 
861     // clean and invalidate cache ops through mem obj of the frame
862     memObj->cleanInvalidateCache(main_frame->buf_idx);
863 
864     if (thumb_frame != NULL) {
865         QCamera3Memory *thumb_memObj = (QCamera3Memory *)thumb_frame->mem_info;
866         if (NULL != thumb_memObj) {
867             // clean and invalidate cache ops through mem obj of the frame
868             thumb_memObj->cleanInvalidateCache(thumb_frame->buf_idx);
869         }
870     }
871 
872     if (mJpegClientHandle <= 0) {
873         ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
874         return UNKNOWN_ERROR;
875     }
876 
877     ALOGD("%s: Need new session?:%d",__func__, needNewSess);
878     if (needNewSess) {
879         //creating a new session, so we must destroy the old one
880         if ( 0 < mJpegSessionId ) {
881             ret = mJpegHandle.destroy_session(mJpegSessionId);
882             if (ret != NO_ERROR) {
883                 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
884                       __func__, mJpegSessionId);
885                 return ret;
886             }
887             mJpegSessionId = 0;
888         }
889         // create jpeg encoding session
890         mm_jpeg_encode_params_t encodeParam;
891         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
892 
893         getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings);
894         ALOGD("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
895                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
896         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
897         if (ret != NO_ERROR) {
898             ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
899             return ret;
900         }
901         needNewSess = FALSE;
902     }
903 
904     // Fill in new job
905     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
906     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
907     jpg_job.encode_job.session_id = mJpegSessionId;
908     jpg_job.encode_job.src_index = main_frame->buf_idx;
909     jpg_job.encode_job.dst_index = 0;
910 
911     cam_rect_t crop;
912     memset(&crop, 0, sizeof(cam_rect_t));
913     //TBD_later - Zoom event removed in stream
914     //main_stream->getCropInfo(crop);
915 
916     cam_dimension_t src_dim;
917     memset(&src_dim, 0, sizeof(cam_dimension_t));
918     main_stream->getFrameDimension(src_dim);
919 
920     cam_dimension_t dst_dim;
921     memset(&dst_dim, 0, sizeof(cam_dimension_t));
922     srcChannel->getStreamByIndex(0)->getFrameDimension(dst_dim);
923 
924     // main dim
925     jpg_job.encode_job.main_dim.src_dim = src_dim;
926     jpg_job.encode_job.main_dim.dst_dim = dst_dim;
927     jpg_job.encode_job.main_dim.crop = crop;
928 
929     // get exif data
930     if (m_pJpegExifObj != NULL) {
931         delete m_pJpegExifObj;
932         m_pJpegExifObj = NULL;
933     }
934     m_pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings);
935     if (m_pJpegExifObj != NULL) {
936         jpg_job.encode_job.exif_info.exif_data = m_pJpegExifObj->getEntries();
937         jpg_job.encode_job.exif_info.numOfEntries =
938           m_pJpegExifObj->getNumOfEntries();
939     }
940     // thumbnail dim
941     ALOGD("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
942     if (m_bThumbnailNeeded == TRUE) {
943         if (thumb_stream == NULL) {
944             // need jpeg thumbnail, but no postview/preview stream exists
945             // we use the main stream/frame to encode thumbnail
946             thumb_stream = main_stream;
947             thumb_frame = main_frame;
948         }
949         memset(&crop, 0, sizeof(cam_rect_t));
950         //TBD_later - Zoom event removed in stream
951         //thumb_stream->getCropInfo(crop);
952         jpg_job.encode_job.thumb_dim.dst_dim =
953                 jpeg_settings->thumbnail_size;
954 
955         if (!hal_obj->needRotationReprocess()) {
956             memset(&src_dim, 0, sizeof(cam_dimension_t));
957             thumb_stream->getFrameDimension(src_dim);
958             jpg_job.encode_job.rotation =
959                     jpeg_settings->jpeg_orientation;
960             ALOGD("%s: jpeg rotation is set to %d", __func__,
961                     jpg_job.encode_job.rotation);
962         } else if (jpeg_settings->jpeg_orientation  == 90 ||
963                 jpeg_settings->jpeg_orientation == 270) {
964            //swap the thumbnail destination width and height if it has already been rotated
965             int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
966             jpg_job.encode_job.thumb_dim.dst_dim.width =
967                     jpg_job.encode_job.thumb_dim.dst_dim.height;
968             jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
969         }
970         jpg_job.encode_job.thumb_dim.src_dim = src_dim;
971         jpg_job.encode_job.thumb_dim.crop = crop;
972         jpg_job.encode_job.thumb_index = thumb_frame->buf_idx;
973     }
974 
975     if (metadata != NULL) {
976        //Fill in the metadata passed as parameter
977        jpg_job.encode_job.p_metadata_v3 = metadata;
978     } else {
979        ALOGE("%s: Metadata is null", __func__);
980     }
981     //Not required here
982     //jpg_job.encode_job.cam_exif_params = m_parent->mExifParams;
983     //Start jpeg encoding
984     ret = mJpegHandle.start_job(&jpg_job, &jobId);
985     if (ret == NO_ERROR) {
986         // remember job info
987         jpeg_job_data->jobId = jobId;
988     }
989 
990     ALOGV("%s : X", __func__);
991     return ret;
992 }
993 
994 /*===========================================================================
995  * FUNCTION   : dataProcessRoutine
996  *
997  * DESCRIPTION: data process routine that handles input data either from input
998  *              Jpeg Queue to do jpeg encoding, or from input PP Queue to do
999  *              reprocess.
1000  *
1001  * PARAMETERS :
1002  *   @data    : user data ptr (QCamera3PostProcessor)
1003  *
1004  * RETURN     : None
1005  *==========================================================================*/
dataProcessRoutine(void * data)1006 void *QCamera3PostProcessor::dataProcessRoutine(void *data)
1007 {
1008     int running = 1;
1009     int ret;
1010     uint8_t is_active = FALSE;
1011     uint8_t needNewSess = TRUE;
1012     mm_camera_super_buf_t *pp_frame = NULL;
1013     metadata_buffer_t *meta_buffer = NULL;
1014     ALOGV("%s: E", __func__);
1015     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
1016     QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
1017     cmdThread->setName("cam_data_proc");
1018 
1019     do {
1020         do {
1021             ret = cam_sem_wait(&cmdThread->cmd_sem);
1022             if (ret != 0 && errno != EINVAL) {
1023                 ALOGE("%s: cam_sem_wait error (%s)",
1024                            __func__, strerror(errno));
1025                 return NULL;
1026             }
1027         } while (ret != 0);
1028 
1029         // we got notified about new cmd avail in cmd queue
1030         camera_cmd_type_t cmd = cmdThread->getCmd();
1031         switch (cmd) {
1032         case CAMERA_CMD_TYPE_START_DATA_PROC:
1033             ALOGD("%s: start data proc", __func__);
1034             is_active = TRUE;
1035             needNewSess = TRUE;
1036 
1037             pme->m_ongoingPPQ.init();
1038             pme->m_inputJpegQ.init();
1039             pme->m_inputPPQ.init();
1040             pme->m_inputRawQ.init();
1041             pme->m_inputMetaQ.init();
1042             pme->m_ongoingJpegQ.init();
1043             pme->m_jpegSettingsQ.init();
1044 
1045             break;
1046         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
1047             {
1048                 ALOGD("%s: stop data proc", __func__);
1049                 is_active = FALSE;
1050 
1051                 // cancel all ongoing jpeg jobs
1052                 qcamera_jpeg_data_t *jpeg_job =
1053                     (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1054                 while (jpeg_job != NULL) {
1055                     pme->mJpegHandle.abort_job(jpeg_job->jobId);
1056 
1057                     pme->releaseJpegJobData(jpeg_job);
1058                     free(jpeg_job);
1059 
1060                     jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1061                 }
1062 
1063                 // destroy jpeg encoding session
1064                 if ( 0 < pme->mJpegSessionId ) {
1065                     pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
1066                     pme->mJpegSessionId = 0;
1067                 }
1068 
1069                 // free jpeg exif obj
1070                 if (pme->m_pJpegExifObj != NULL) {
1071                     delete pme->m_pJpegExifObj;
1072                     pme->m_pJpegExifObj = NULL;
1073                 }
1074                 needNewSess = TRUE;
1075 
1076                 // flush ongoing postproc Queue
1077                 pme->m_ongoingPPQ.flush();
1078 
1079                 // flush input jpeg Queue
1080                 pme->m_inputJpegQ.flush();
1081 
1082                 // flush input Postproc Queue
1083                 pme->m_inputPPQ.flush();
1084 
1085                 // flush input raw Queue
1086                 pme->m_inputRawQ.flush();
1087 
1088                 pme->m_inputMetaQ.flush();
1089 
1090                 // signal cmd is completed
1091                 cam_sem_post(&cmdThread->sync_sem);
1092             }
1093             break;
1094         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
1095             {
1096                 ALOGD("%s: Do next job, active is %d", __func__, is_active);
1097                 if (is_active == TRUE) {
1098                     // check if there is any ongoing jpeg jobs
1099                     if (pme->m_ongoingJpegQ.isEmpty()) {
1100                        ALOGI("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
1101                         // no ongoing jpeg job, we are fine to send jpeg encoding job
1102                         qcamera_jpeg_data_t *jpeg_job =
1103                             (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1104 
1105                         if (NULL != jpeg_job) {
1106                             // add into ongoing jpeg job Q
1107                             pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
1108                             ret = pme->encodeData(jpeg_job, needNewSess);
1109                             if (NO_ERROR != ret) {
1110                                 // dequeue the last one
1111                                 pme->m_ongoingJpegQ.dequeue(false);
1112 
1113                                 pme->releaseJpegJobData(jpeg_job);
1114                                 free(jpeg_job);
1115                             }
1116                         }
1117                     }
1118                     ALOGD("%s: dequeuing pp frame", __func__);
1119                     pp_frame =
1120                         (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
1121                     meta_buffer =
1122                         (metadata_buffer_t *)pme->m_inputMetaQ.dequeue();
1123                     if (NULL != pp_frame && NULL != meta_buffer) {
1124                         qcamera_pp_data_t *pp_job =
1125                             (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t));
1126                         if (pp_job != NULL) {
1127                             memset(pp_job, 0, sizeof(qcamera_pp_data_t));
1128                             if (pme->m_pReprocChannel != NULL) {
1129                                 // add into ongoing PP job Q
1130                                 pp_job->src_frame = pp_frame;
1131                                 pp_job->metadata = meta_buffer;
1132                                 pme->m_ongoingPPQ.enqueue((void *)pp_job);
1133                                 ret = pme->m_pReprocChannel->doReprocessOffline(pp_frame, meta_buffer);
1134                                 if (NO_ERROR != ret) {
1135                                     // remove from ongoing PP job Q
1136                                     pme->m_ongoingPPQ.dequeue(false);
1137                                 }
1138                             } else {
1139                                 ALOGE("%s: Reprocess channel is NULL", __func__);
1140                                 ret = -1;
1141                             }
1142                         } else {
1143                             ALOGE("%s: no mem for qcamera_pp_data_t", __func__);
1144                             ret = -1;
1145                         }
1146 
1147                         if (0 != ret) {
1148                             // free pp_job
1149                             if (pp_job != NULL) {
1150                                 free(pp_job);
1151                             }
1152                             // free frame
1153                             if (pp_frame != NULL) {
1154                                 pme->releaseSuperBuf(pp_frame);
1155                                 free(pp_frame);
1156                             }
1157                         }
1158                     }
1159                 } else {
1160                     // not active, simply return buf and do no op
1161                     mm_camera_super_buf_t *super_buf;
1162                     qcamera_jpeg_data_t *jpeg_job =
1163                         (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1164                     if (NULL != jpeg_job) {
1165                         free(jpeg_job);
1166                     }
1167                     super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
1168                     if (NULL != super_buf) {
1169                         pme->releaseSuperBuf(super_buf);
1170                         free(super_buf);
1171                     }
1172                     super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
1173                     if (NULL != super_buf) {
1174                         pme->releaseSuperBuf(super_buf);
1175                         free(super_buf);
1176                     }
1177                     super_buf = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
1178                     if (NULL != super_buf) {
1179                         pme->releaseSuperBuf(super_buf);
1180                         free(super_buf);
1181                     }
1182                 }
1183             }
1184             break;
1185         case CAMERA_CMD_TYPE_EXIT:
1186             running = 0;
1187             break;
1188         default:
1189             break;
1190         }
1191     } while (running);
1192     ALOGV("%s: X", __func__);
1193     return NULL;
1194 }
1195 
1196 /*===========================================================================
1197  * FUNCTION   : QCamera3Exif
1198  *
1199  * DESCRIPTION: constructor of QCamera3Exif
1200  *
1201  * PARAMETERS : None
1202  *
1203  * RETURN     : None
1204  *==========================================================================*/
QCamera3Exif()1205 QCamera3Exif::QCamera3Exif()
1206     : m_nNumEntries(0)
1207 {
1208     memset(m_Entries, 0, sizeof(m_Entries));
1209 }
1210 
1211 /*===========================================================================
1212  * FUNCTION   : ~QCamera3Exif
1213  *
1214  * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
1215  *
1216  * PARAMETERS : None
1217  *
1218  * RETURN     : None
1219  *==========================================================================*/
~QCamera3Exif()1220 QCamera3Exif::~QCamera3Exif()
1221 {
1222     for (uint32_t i = 0; i < m_nNumEntries; i++) {
1223         switch (m_Entries[i].tag_entry.type) {
1224             case EXIF_BYTE:
1225                 {
1226                     if (m_Entries[i].tag_entry.count > 1 &&
1227                             m_Entries[i].tag_entry.data._bytes != NULL) {
1228                         free(m_Entries[i].tag_entry.data._bytes);
1229                         m_Entries[i].tag_entry.data._bytes = NULL;
1230                     }
1231                 }
1232                 break;
1233             case EXIF_ASCII:
1234                 {
1235                     if (m_Entries[i].tag_entry.data._ascii != NULL) {
1236                         free(m_Entries[i].tag_entry.data._ascii);
1237                         m_Entries[i].tag_entry.data._ascii = NULL;
1238                     }
1239                 }
1240                 break;
1241             case EXIF_SHORT:
1242                 {
1243                     if (m_Entries[i].tag_entry.count > 1 &&
1244                             m_Entries[i].tag_entry.data._shorts != NULL) {
1245                         free(m_Entries[i].tag_entry.data._shorts);
1246                         m_Entries[i].tag_entry.data._shorts = NULL;
1247                     }
1248                 }
1249                 break;
1250             case EXIF_LONG:
1251                 {
1252                     if (m_Entries[i].tag_entry.count > 1 &&
1253                             m_Entries[i].tag_entry.data._longs != NULL) {
1254                         free(m_Entries[i].tag_entry.data._longs);
1255                         m_Entries[i].tag_entry.data._longs = NULL;
1256                     }
1257                 }
1258                 break;
1259             case EXIF_RATIONAL:
1260                 {
1261                     if (m_Entries[i].tag_entry.count > 1 &&
1262                             m_Entries[i].tag_entry.data._rats != NULL) {
1263                         free(m_Entries[i].tag_entry.data._rats);
1264                         m_Entries[i].tag_entry.data._rats = NULL;
1265                     }
1266                 }
1267                 break;
1268             case EXIF_UNDEFINED:
1269                 {
1270                     if (m_Entries[i].tag_entry.data._undefined != NULL) {
1271                         free(m_Entries[i].tag_entry.data._undefined);
1272                         m_Entries[i].tag_entry.data._undefined = NULL;
1273                     }
1274                 }
1275                 break;
1276             case EXIF_SLONG:
1277                 {
1278                     if (m_Entries[i].tag_entry.count > 1 &&
1279                             m_Entries[i].tag_entry.data._slongs != NULL) {
1280                         free(m_Entries[i].tag_entry.data._slongs);
1281                         m_Entries[i].tag_entry.data._slongs = NULL;
1282                     }
1283                 }
1284                 break;
1285             case EXIF_SRATIONAL:
1286                 {
1287                     if (m_Entries[i].tag_entry.count > 1 &&
1288                             m_Entries[i].tag_entry.data._srats != NULL) {
1289                         free(m_Entries[i].tag_entry.data._srats);
1290                         m_Entries[i].tag_entry.data._srats = NULL;
1291                     }
1292                 }
1293                 break;
1294             default:
1295                 ALOGE("%s: Error, Unknown type",__func__);
1296                 break;
1297         }
1298     }
1299 }
1300 
1301 /*===========================================================================
1302  * FUNCTION   : addEntry
1303  *
1304  * DESCRIPTION: function to add an entry to exif data
1305  *
1306  * PARAMETERS :
1307  *   @tagid   : exif tag ID
1308  *   @type    : data type
1309  *   @count   : number of data in uint of its type
1310  *   @data    : input data ptr
1311  *
1312  * RETURN     : int32_t type of status
1313  *              NO_ERROR  -- success
1314  *              none-zero failure code
1315  *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)1316 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
1317                               exif_tag_type_t type,
1318                               uint32_t count,
1319                               void *data)
1320 {
1321     int32_t rc = NO_ERROR;
1322     if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) {
1323         ALOGE("%s: Number of entries exceeded limit", __func__);
1324         return NO_MEMORY;
1325     }
1326 
1327     m_Entries[m_nNumEntries].tag_id = tagid;
1328     m_Entries[m_nNumEntries].tag_entry.type = type;
1329     m_Entries[m_nNumEntries].tag_entry.count = count;
1330     m_Entries[m_nNumEntries].tag_entry.copy = 1;
1331     switch (type) {
1332         case EXIF_BYTE:
1333             {
1334                 if (count > 1) {
1335                     uint8_t *values = (uint8_t *)malloc(count);
1336                     if (values == NULL) {
1337                         ALOGE("%s: No memory for byte array", __func__);
1338                         rc = NO_MEMORY;
1339                     } else {
1340                         memcpy(values, data, count);
1341                         m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
1342                     }
1343                 } else {
1344                     m_Entries[m_nNumEntries].tag_entry.data._byte =
1345                         *(uint8_t *)data;
1346                 }
1347             }
1348             break;
1349         case EXIF_ASCII:
1350             {
1351                 char *str = NULL;
1352                 str = (char *)malloc(count + 1);
1353                 if (str == NULL) {
1354                     ALOGE("%s: No memory for ascii string", __func__);
1355                     rc = NO_MEMORY;
1356                 } else {
1357                     memset(str, 0, count + 1);
1358                     memcpy(str, data, count);
1359                     m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
1360                 }
1361             }
1362             break;
1363         case EXIF_SHORT:
1364             {
1365                 if (count > 1) {
1366                     uint16_t *values =
1367                         (uint16_t *)malloc(count * sizeof(uint16_t));
1368                     if (values == NULL) {
1369                         ALOGE("%s: No memory for short array", __func__);
1370                         rc = NO_MEMORY;
1371                     } else {
1372                         memcpy(values, data, count * sizeof(uint16_t));
1373                         m_Entries[m_nNumEntries].tag_entry.data._shorts =values;
1374                     }
1375                 } else {
1376                     m_Entries[m_nNumEntries].tag_entry.data._short =
1377                         *(uint16_t *)data;
1378                 }
1379             }
1380             break;
1381         case EXIF_LONG:
1382             {
1383                 if (count > 1) {
1384                     uint32_t *values =
1385                         (uint32_t *)malloc(count * sizeof(uint32_t));
1386                     if (values == NULL) {
1387                         ALOGE("%s: No memory for long array", __func__);
1388                         rc = NO_MEMORY;
1389                     } else {
1390                         memcpy(values, data, count * sizeof(uint32_t));
1391                         m_Entries[m_nNumEntries].tag_entry.data._longs = values;
1392                     }
1393                 } else {
1394                     m_Entries[m_nNumEntries].tag_entry.data._long =
1395                         *(uint32_t *)data;
1396                 }
1397             }
1398             break;
1399         case EXIF_RATIONAL:
1400             {
1401                 if (count > 1) {
1402                     rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
1403                     if (values == NULL) {
1404                         ALOGE("%s: No memory for rational array", __func__);
1405                         rc = NO_MEMORY;
1406                     } else {
1407                         memcpy(values, data, count * sizeof(rat_t));
1408                         m_Entries[m_nNumEntries].tag_entry.data._rats = values;
1409                     }
1410                 } else {
1411                     m_Entries[m_nNumEntries].tag_entry.data._rat =
1412                         *(rat_t *)data;
1413                 }
1414             }
1415             break;
1416         case EXIF_UNDEFINED:
1417             {
1418                 uint8_t *values = (uint8_t *)malloc(count);
1419                 if (values == NULL) {
1420                     ALOGE("%s: No memory for undefined array", __func__);
1421                     rc = NO_MEMORY;
1422                 } else {
1423                     memcpy(values, data, count);
1424                     m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
1425                 }
1426             }
1427             break;
1428         case EXIF_SLONG:
1429             {
1430                 if (count > 1) {
1431                     int32_t *values =
1432                         (int32_t *)malloc(count * sizeof(int32_t));
1433                     if (values == NULL) {
1434                         ALOGE("%s: No memory for signed long array", __func__);
1435                         rc = NO_MEMORY;
1436                     } else {
1437                         memcpy(values, data, count * sizeof(int32_t));
1438                         m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
1439                     }
1440                 } else {
1441                     m_Entries[m_nNumEntries].tag_entry.data._slong =
1442                         *(int32_t *)data;
1443                 }
1444             }
1445             break;
1446         case EXIF_SRATIONAL:
1447             {
1448                 if (count > 1) {
1449                     srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
1450                     if (values == NULL) {
1451                         ALOGE("%s: No memory for sign rational array",__func__);
1452                         rc = NO_MEMORY;
1453                     } else {
1454                         memcpy(values, data, count * sizeof(srat_t));
1455                         m_Entries[m_nNumEntries].tag_entry.data._srats = values;
1456                     }
1457                 } else {
1458                     m_Entries[m_nNumEntries].tag_entry.data._srat =
1459                         *(srat_t *)data;
1460                 }
1461             }
1462             break;
1463         default:
1464             ALOGE("%s: Error, Unknown type",__func__);
1465             break;
1466     }
1467 
1468     // Increase number of entries
1469     m_nNumEntries++;
1470     return rc;
1471 }
1472 
1473 }; // namespace qcamera
1474