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