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