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