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