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