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