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