1 /* Copyright (c) 2012-2015, 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 #define ATRACE_TAG ATRACE_TAG_CAMERA
30
31 #define LOG_TAG "QCamera3PostProc"
32 //#define LOG_NDEBUG 0
33
34 #include <stdlib.h>
35 #include <utils/Errors.h>
36 #include <utils/Trace.h>
37
38 #include "QCamera3PostProc.h"
39 #include "QCamera3HWI.h"
40 #include "QCamera3Channel.h"
41 #include "QCamera3Stream.h"
42
43 namespace qcamera {
44
45 /*===========================================================================
46 * FUNCTION : QCamera3PostProcessor
47 *
48 * DESCRIPTION: constructor of QCamera3PostProcessor.
49 *
50 * PARAMETERS :
51 * @cam_ctrl : ptr to HWI object
52 *
53 * RETURN : None
54 *==========================================================================*/
QCamera3PostProcessor(QCamera3PicChannel * ch_ctrl)55 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3PicChannel* ch_ctrl)
56 : m_parent(ch_ctrl),
57 mJpegCB(NULL),
58 mJpegUserData(NULL),
59 mJpegClientHandle(0),
60 mJpegSessionId(0),
61 m_bThumbnailNeeded(TRUE),
62 m_pReprocChannel(NULL),
63 m_inputPPQ(releasePPInputData, this),
64 m_inputFWKPPQ(NULL, this),
65 m_ongoingPPQ(releaseOngoingPPData, this),
66 m_inputJpegQ(releaseJpegData, this),
67 m_ongoingJpegQ(releaseJpegData, this),
68 m_inputRawQ(releasePPInputData, this),
69 m_inputMetaQ(releaseMetadata, this),
70 m_jpegSettingsQ(NULL, this)
71 {
72 memset(&mJpegHandle, 0, sizeof(mJpegHandle));
73 pthread_mutex_init(&mReprocJobLock, NULL);
74 }
75
76 /*===========================================================================
77 * FUNCTION : ~QCamera3PostProcessor
78 *
79 * DESCRIPTION: deconstructor of QCamera3PostProcessor.
80 *
81 * PARAMETERS : None
82 *
83 * RETURN : None
84 *==========================================================================*/
~QCamera3PostProcessor()85 QCamera3PostProcessor::~QCamera3PostProcessor()
86 {
87 pthread_mutex_destroy(&mReprocJobLock);
88 }
89
90 /*===========================================================================
91 * FUNCTION : init
92 *
93 * DESCRIPTION: initialization of postprocessor
94 *
95 * PARAMETERS :
96 * @jpeg_cb : callback to handle jpeg event from mm-camera-interface
97 * @user_data : user data ptr for jpeg callback
98 *
99 * RETURN : int32_t type of status
100 * NO_ERROR -- success
101 * none-zero failure code
102 *==========================================================================*/
init(QCamera3Memory * mMemory,jpeg_encode_callback_t jpeg_cb,uint32_t postprocess_mask,void * user_data)103 int32_t QCamera3PostProcessor::init(QCamera3Memory* mMemory,
104 jpeg_encode_callback_t jpeg_cb,
105 uint32_t postprocess_mask,
106 void *user_data)
107 {
108 ATRACE_CALL();
109 mJpegCB = jpeg_cb;
110 mJpegUserData = user_data;
111 mm_dimension max_size;
112
113 //set max pic size
114 memset(&max_size, 0, sizeof(mm_dimension));
115 max_size.w = m_parent->m_max_pic_dim.width;
116 max_size.h = m_parent->m_max_pic_dim.height;
117
118 mJpegClientHandle = jpeg_open(&mJpegHandle,max_size);
119 mJpegMem = mMemory;
120 if(!mJpegClientHandle) {
121 ALOGE("%s : jpeg_open did not work", __func__);
122 return UNKNOWN_ERROR;
123 }
124 mPostProcMask = postprocess_mask;
125 m_dataProcTh.launch(dataProcessRoutine, this);
126
127 return NO_ERROR;
128 }
129
130 /*===========================================================================
131 * FUNCTION : deinit
132 *
133 * DESCRIPTION: de-initialization of postprocessor
134 *
135 * PARAMETERS : None
136 *
137 * RETURN : int32_t type of status
138 * NO_ERROR -- success
139 * none-zero failure code
140 *==========================================================================*/
deinit()141 int32_t QCamera3PostProcessor::deinit()
142 {
143 m_dataProcTh.exit();
144
145 if (m_pReprocChannel != NULL) {
146 m_pReprocChannel->stop();
147 delete m_pReprocChannel;
148 m_pReprocChannel = NULL;
149 }
150
151 if(mJpegClientHandle > 0) {
152 int rc = mJpegHandle.close(mJpegClientHandle);
153 CDBG_HIGH("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
154 __func__, rc, mJpegClientHandle);
155 mJpegClientHandle = 0;
156 memset(&mJpegHandle, 0, sizeof(mJpegHandle));
157 }
158
159 mJpegMem = NULL;
160
161 return NO_ERROR;
162 }
163
164 /*===========================================================================
165 * FUNCTION : start
166 *
167 * DESCRIPTION: start postprocessor. Data process thread and data notify thread
168 * will be launched.
169 *
170 * PARAMETERS :
171 * @pMemory : memory object representing buffers to store JPEG.
172 * @config : reprocess configuration
173 * @metadata : metadata for the reprocessing
174 *
175 * RETURN : int32_t type of status
176 * NO_ERROR -- success
177 * none-zero failure code
178 *
179 * NOTE : if any reprocess is needed, a reprocess channel/stream
180 * will be started.
181 *==========================================================================*/
start(const reprocess_config_t & config,metadata_buffer_t * metadata)182 int32_t QCamera3PostProcessor::start(const reprocess_config_t &config,
183 metadata_buffer_t *metadata)
184 {
185 int32_t rc = NO_ERROR;
186 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
187
188 if (hal_obj->needReprocess(mPostProcMask) || config.src_channel != m_parent) {
189 if (m_pReprocChannel != NULL) {
190 m_pReprocChannel->stop();
191 delete m_pReprocChannel;
192 m_pReprocChannel = NULL;
193 }
194
195 // if reprocess is needed, start reprocess channel
196 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
197 CDBG("%s: Setting input channel as pInputChannel", __func__);
198 m_pReprocChannel = hal_obj->addOfflineReprocChannel(config, m_parent, metadata);
199 if (m_pReprocChannel == NULL) {
200 ALOGE("%s: cannot add reprocess channel", __func__);
201 return UNKNOWN_ERROR;
202 }
203
204 rc = m_pReprocChannel->start();
205 if (rc != 0) {
206 ALOGE("%s: cannot start reprocess channel", __func__);
207 delete m_pReprocChannel;
208 m_pReprocChannel = NULL;
209 return rc;
210 }
211 }
212 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE);
213
214 return rc;
215 }
216
217 /*===========================================================================
218 * FUNCTION : stop
219 *
220 * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
221 *
222 * PARAMETERS : None
223 *
224 * RETURN : int32_t type of status
225 * NO_ERROR -- success
226 * none-zero failure code
227 *
228 * NOTE : reprocess channel will be stopped and deleted if there is any
229 *==========================================================================*/
stop()230 int32_t QCamera3PostProcessor::stop()
231 {
232 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
233
234 if (m_pReprocChannel != NULL) {
235 m_pReprocChannel->stop();
236 delete m_pReprocChannel;
237 m_pReprocChannel = NULL;
238 }
239
240 return NO_ERROR;
241 }
242
243 /*===========================================================================
244 * FUNCTION : getFWKJpegEncodeConfig
245 *
246 * DESCRIPTION: function to prepare encoding job information
247 *
248 * PARAMETERS :
249 * @encode_parm : param to be filled with encoding configuration
250 * @frame : framework input buffer
251 * @jpeg_settings : jpeg settings to be applied for encoding
252 *
253 * RETURN : int32_t type of status
254 * NO_ERROR -- success
255 * none-zero failure code
256 *==========================================================================*/
getFWKJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,qcamera_fwk_input_pp_data_t * frame,jpeg_settings_t * jpeg_settings)257 int32_t QCamera3PostProcessor::getFWKJpegEncodeConfig(
258 mm_jpeg_encode_params_t& encode_parm,
259 qcamera_fwk_input_pp_data_t *frame,
260 jpeg_settings_t *jpeg_settings)
261 {
262 CDBG("%s : E", __func__);
263
264 if ((NULL == frame) || (NULL == jpeg_settings)) {
265 return BAD_VALUE;
266 }
267
268 encode_parm.jpeg_cb = mJpegCB;
269 encode_parm.userdata = mJpegUserData;
270
271 if (jpeg_settings->thumbnail_size.width > 0 &&
272 jpeg_settings->thumbnail_size.height > 0)
273 m_bThumbnailNeeded = TRUE;
274 else
275 m_bThumbnailNeeded = FALSE;
276 encode_parm.encode_thumbnail = m_bThumbnailNeeded;
277
278 // get color format
279 cam_format_t img_fmt = frame->reproc_config.stream_format;
280 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
281
282 // get jpeg quality
283 encode_parm.quality = jpeg_settings->jpeg_quality;
284 if (encode_parm.quality <= 0) {
285 encode_parm.quality = 85;
286 }
287
288 // get jpeg thumbnail quality
289 encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
290
291 cam_frame_len_offset_t main_offset =
292 frame->reproc_config.input_stream_plane_info.plane_info;
293
294 encode_parm.num_src_bufs = 1;
295 encode_parm.src_main_buf[0].index = 0;
296 encode_parm.src_main_buf[0].buf_size = frame->input_buffer.frame_len;
297 encode_parm.src_main_buf[0].buf_vaddr = (uint8_t *) frame->input_buffer.buffer;
298 encode_parm.src_main_buf[0].fd = frame->input_buffer.fd;
299 encode_parm.src_main_buf[0].format = MM_JPEG_FMT_YUV;
300 encode_parm.src_main_buf[0].offset = main_offset;
301
302 //Pass input thumbnail buffer info to encoder.
303 //Note: Use main buffer to encode thumbnail
304 if (m_bThumbnailNeeded == TRUE) {
305 encode_parm.num_tmb_bufs = 1;
306 encode_parm.src_thumb_buf[0] = encode_parm.src_main_buf[0];
307 }
308
309 //Pass output jpeg buffer info to encoder.
310 //mJpegMem is allocated by framework.
311 encode_parm.num_dst_bufs = 1;
312 encode_parm.dest_buf[0].index = 0;
313 encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(
314 jpeg_settings->out_buf_index);
315 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(
316 jpeg_settings->out_buf_index);
317 encode_parm.dest_buf[0].fd = mJpegMem->getFd(
318 jpeg_settings->out_buf_index);
319 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
320 encode_parm.dest_buf[0].offset = main_offset;
321
322 CDBG("%s : X", __func__);
323 return NO_ERROR;
324 }
325
326 /*===========================================================================
327 * FUNCTION : getJpegEncodeConfig
328 *
329 * DESCRIPTION: function to prepare encoding job information
330 *
331 * PARAMETERS :
332 * @encode_parm : param to be filled with encoding configuration
333 * #main_stream : stream object where the input buffer comes from
334 * @jpeg_settings : jpeg settings to be applied for encoding
335 *
336 * RETURN : int32_t type of status
337 * NO_ERROR -- success
338 * none-zero failure code
339 *==========================================================================*/
getJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,QCamera3Stream * main_stream,jpeg_settings_t * jpeg_settings)340 int32_t QCamera3PostProcessor::getJpegEncodeConfig(
341 mm_jpeg_encode_params_t& encode_parm,
342 QCamera3Stream *main_stream,
343 jpeg_settings_t *jpeg_settings)
344 {
345 CDBG("%s : E", __func__);
346 int32_t ret = NO_ERROR;
347
348 encode_parm.jpeg_cb = mJpegCB;
349 encode_parm.userdata = mJpegUserData;
350
351 if (jpeg_settings->thumbnail_size.width > 0 &&
352 jpeg_settings->thumbnail_size.height > 0)
353 m_bThumbnailNeeded = TRUE;
354 else
355 m_bThumbnailNeeded = FALSE;
356 encode_parm.encode_thumbnail = m_bThumbnailNeeded;
357
358 // get color format
359 cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12; //default value
360 main_stream->getFormat(img_fmt);
361 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
362
363 //get rotation
364 encode_parm.jpeg_orientation = jpeg_settings->jpeg_orientation;
365
366 // get jpeg quality
367 encode_parm.quality = jpeg_settings->jpeg_quality;
368 if (encode_parm.quality <= 0) {
369 encode_parm.quality = 85;
370 }
371
372 // get jpeg thumbnail quality
373 encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
374
375 cam_frame_len_offset_t main_offset;
376 memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
377 main_stream->getFrameOffset(main_offset);
378
379 // src buf config
380 //Pass input main image buffer info to encoder.
381 QCamera3Memory *pStreamMem = main_stream->getStreamBufs();
382 if (pStreamMem == NULL) {
383 ALOGE("%s: cannot get stream bufs from main stream", __func__);
384 ret = BAD_VALUE;
385 goto on_error;
386 }
387 encode_parm.num_src_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
388 for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
389 if (pStreamMem != NULL) {
390 encode_parm.src_main_buf[i].index = i;
391 encode_parm.src_main_buf[i].buf_size = pStreamMem->getSize(i);
392 encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
393 encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
394 encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
395 encode_parm.src_main_buf[i].offset = main_offset;
396 }
397 }
398
399 //Pass input thumbnail buffer info to encoder.
400 //Note: Use main buffer to encode thumbnail
401 if (m_bThumbnailNeeded == TRUE) {
402 pStreamMem = main_stream->getStreamBufs();
403 if (pStreamMem == NULL) {
404 ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
405 ret = BAD_VALUE;
406 goto on_error;
407 }
408 cam_frame_len_offset_t thumb_offset;
409 memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
410 main_stream->getFrameOffset(thumb_offset);
411 encode_parm.num_tmb_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
412 for (size_t i = 0; i < encode_parm.num_tmb_bufs; i++) {
413 if (pStreamMem != NULL) {
414 encode_parm.src_thumb_buf[i].index = i;
415 encode_parm.src_thumb_buf[i].buf_size = pStreamMem->getSize(i);
416 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
417 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
418 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
419 encode_parm.src_thumb_buf[i].offset = thumb_offset;
420 }
421 }
422 }
423
424 //Pass output jpeg buffer info to encoder.
425 //mJpegMem is allocated by framework.
426 encode_parm.num_dst_bufs = 1;
427 encode_parm.dest_buf[0].index = 0;
428 encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(
429 jpeg_settings->out_buf_index);
430 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(
431 jpeg_settings->out_buf_index);
432 encode_parm.dest_buf[0].fd = mJpegMem->getFd(
433 jpeg_settings->out_buf_index);
434 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
435 encode_parm.dest_buf[0].offset = main_offset;
436
437 CDBG("%s : X", __func__);
438 return NO_ERROR;
439
440 on_error:
441 CDBG("%s : X with error %d", __func__, ret);
442 return ret;
443 }
444
445 /*===========================================================================
446 * FUNCTION : processData
447 *
448 * DESCRIPTION: enqueue data into dataProc thread
449 *
450 * PARAMETERS :
451 * @frame : process frame
452 *
453 * RETURN : int32_t type of status
454 * NO_ERROR -- success
455 * none-zero failure code
456 *
457 * NOTE : depends on if offline reprocess is needed, received frame will
458 * be sent to either input queue of postprocess or jpeg encoding
459 *==========================================================================*/
processData(mm_camera_super_buf_t * frame)460 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame)
461 {
462 pthread_mutex_lock(&mReprocJobLock);
463 // enqueue to post proc input queue
464 m_inputPPQ.enqueue((void *)frame);
465 if (!(m_inputMetaQ.isEmpty())) {
466 CDBG("%s: meta queue is not empty, do next job", __func__);
467 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
468 }
469 pthread_mutex_unlock(&mReprocJobLock);
470
471 return NO_ERROR;
472 }
473
474 /*===========================================================================
475 * FUNCTION : processData
476 *
477 * DESCRIPTION: enqueue data into dataProc thread
478 *
479 * PARAMETERS :
480 * @frame : process frame
481 *
482 * RETURN : int32_t type of status
483 * NO_ERROR -- success
484 * none-zero failure code
485 *
486 * NOTE : depends on if offline reprocess is needed, received frame will
487 * be sent to either input queue of postprocess or jpeg encoding
488 *==========================================================================*/
processData(qcamera_fwk_input_pp_data_t * frame)489 int32_t QCamera3PostProcessor::processData(qcamera_fwk_input_pp_data_t *frame)
490 {
491 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
492 if (hal_obj->needReprocess(mPostProcMask) ||
493 frame->reproc_config.src_channel != m_parent) {
494 pthread_mutex_lock(&mReprocJobLock);
495 // enqueu to post proc input queue
496 m_inputFWKPPQ.enqueue((void *)frame);
497 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
498 pthread_mutex_unlock(&mReprocJobLock);
499 } else {
500 jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue();
501
502 if (jpeg_settings == NULL) {
503 ALOGE("%s: Cannot find jpeg settings", __func__);
504 return BAD_VALUE;
505 }
506
507 CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__);
508 qcamera_hal3_jpeg_data_t *jpeg_job =
509 (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
510 if (jpeg_job == NULL) {
511 ALOGE("%s: No memory for jpeg job", __func__);
512 return NO_MEMORY;
513 }
514
515 memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
516 jpeg_job->fwk_frame = frame;
517 jpeg_job->jpeg_settings = jpeg_settings;
518 jpeg_job->metadata =
519 (metadata_buffer_t *) frame->metadata_buffer.buffer;
520
521 // enqueu to jpeg input queue
522 m_inputJpegQ.enqueue((void *)jpeg_job);
523 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
524 }
525
526 return NO_ERROR;
527 }
528
529 /*===========================================================================
530 * FUNCTION : processPPMetadata
531 *
532 * DESCRIPTION: enqueue data into dataProc thread
533 *
534 * PARAMETERS :
535 * @frame : process metadata frame received from pic channel
536 *
537 * RETURN : int32_t type of status
538 * NO_ERROR -- success
539 * none-zero failure code
540 *
541 *==========================================================================*/
processPPMetadata(mm_camera_super_buf_t * reproc_meta)542 int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta)
543 {
544 pthread_mutex_lock(&mReprocJobLock);
545 // enqueue to metadata input queue
546 m_inputMetaQ.enqueue((void *)reproc_meta);
547 if (!(m_inputPPQ.isEmpty())) {
548 CDBG("%s: pp queue is not empty, do next job", __func__);
549 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
550 } else {
551 CDBG("%s: pp queue is empty, not calling do next job", __func__);
552 }
553 pthread_mutex_unlock(&mReprocJobLock);
554 return NO_ERROR;
555 }
556
557 /*===========================================================================
558 * FUNCTION : processJpegSettingData
559 *
560 * DESCRIPTION: enqueue jpegSetting into dataProc thread
561 *
562 * PARAMETERS :
563 * @jpeg_settings : jpeg settings data received from pic channel
564 *
565 * RETURN : int32_t type of status
566 * NO_ERROR -- success
567 * none-zero failure code
568 *
569 *==========================================================================*/
processJpegSettingData(jpeg_settings_t * jpeg_settings)570 int32_t QCamera3PostProcessor::processJpegSettingData(
571 jpeg_settings_t *jpeg_settings)
572 {
573 if (!jpeg_settings) {
574 ALOGE("%s: invalid jpeg settings pointer", __func__);
575 return -EINVAL;
576 }
577 return m_jpegSettingsQ.enqueue((void *)jpeg_settings);
578 }
579
580 /*===========================================================================
581 * FUNCTION : processRawData
582 *
583 * DESCRIPTION: enqueue raw data into dataProc thread
584 *
585 * PARAMETERS :
586 * @frame : process frame received from mm-camera-interface
587 *
588 * RETURN : int32_t type of status
589 * NO_ERROR -- success
590 * none-zero failure code
591 *==========================================================================*/
processRawData(mm_camera_super_buf_t * frame)592 int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame)
593 {
594 // enqueu to raw input queue
595 m_inputRawQ.enqueue((void *)frame);
596 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
597 return NO_ERROR;
598 }
599
600 /*===========================================================================
601 * FUNCTION : processPPData
602 *
603 * DESCRIPTION: process received frame after reprocess.
604 *
605 * PARAMETERS :
606 * @frame : received frame from reprocess channel.
607 *
608 * RETURN : int32_t type of status
609 * NO_ERROR -- success
610 * none-zero failure code
611 *
612 * NOTE : The frame after reprocess need to send to jpeg encoding.
613 *==========================================================================*/
processPPData(mm_camera_super_buf_t * frame)614 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame)
615 {
616 qcamera_hal3_pp_data_t *job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
617
618 if (job == NULL || ((NULL == job->src_frame) && (NULL == job->fwk_src_frame))) {
619 ALOGE("%s: Cannot find reprocess job", __func__);
620 return BAD_VALUE;
621 }
622 if (job->jpeg_settings == NULL) {
623 ALOGE("%s: Cannot find jpeg settings", __func__);
624 return BAD_VALUE;
625 }
626
627 qcamera_hal3_jpeg_data_t *jpeg_job =
628 (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
629 if (jpeg_job == NULL) {
630 ALOGE("%s: No memory for jpeg job", __func__);
631 return NO_MEMORY;
632 }
633
634 memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
635 jpeg_job->src_frame = frame;
636 if(frame != job->src_frame)
637 jpeg_job->src_reproc_frame = job->src_frame;
638 if (NULL == job->fwk_src_frame) {
639 jpeg_job->metadata = job->metadata;
640 } else {
641 jpeg_job->metadata =
642 (metadata_buffer_t *) job->fwk_src_frame->metadata_buffer.buffer;
643 jpeg_job->fwk_src_buffer = job->fwk_src_frame;
644 }
645 jpeg_job->src_metadata = job->src_metadata;
646 jpeg_job->jpeg_settings = job->jpeg_settings;
647
648 // free pp job buf
649 free(job);
650
651 // enqueu reprocessed frame to jpeg input queue
652 m_inputJpegQ.enqueue((void *)jpeg_job);
653
654 // wait up data proc thread
655 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
656
657 return NO_ERROR;
658 }
659
660 /*===========================================================================
661 * FUNCTION : findJpegJobByJobId
662 *
663 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
664 *
665 * PARAMETERS :
666 * @jobId : job Id of the job
667 *
668 * RETURN : ptr to a jpeg job struct. NULL if not found.
669 *
670 * NOTE : Currently only one job is sending to mm-jpeg-interface for jpeg
671 * encoding. Therefore simply dequeue from the ongoing Jpeg Queue
672 * will serve the purpose to find the jpeg job.
673 *==========================================================================*/
findJpegJobByJobId(uint32_t jobId)674 qcamera_hal3_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId)
675 {
676 qcamera_hal3_jpeg_data_t * job = NULL;
677 if (jobId == 0) {
678 ALOGE("%s: not a valid jpeg jobId", __func__);
679 return NULL;
680 }
681
682 // currely only one jpeg job ongoing, so simply dequeue the head
683 job = (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
684 return job;
685 }
686
687 /*===========================================================================
688 * FUNCTION : releasePPInputData
689 *
690 * DESCRIPTION: callback function to release post process input data node
691 *
692 * PARAMETERS :
693 * @data : ptr to post process input data
694 * @user_data : user data ptr (QCamera3Reprocessor)
695 *
696 * RETURN : None
697 *==========================================================================*/
releasePPInputData(void * data,void * user_data)698 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data)
699 {
700 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
701 if (NULL != pme) {
702 pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
703 }
704 }
705
706 /*===========================================================================
707 * FUNCTION : releaseMetaData
708 *
709 * DESCRIPTION: callback function to release metadata camera buffer
710 *
711 * PARAMETERS :
712 * @data : ptr to post process input data
713 * @user_data : user data ptr (QCamera3Reprocessor)
714 *
715 * RETURN : None
716 *==========================================================================*/
releaseMetadata(void * data,void * user_data)717 void QCamera3PostProcessor::releaseMetadata(void *data, void *user_data)
718 {
719 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
720 if (NULL != pme) {
721 pme->m_parent->metadataBufDone((mm_camera_super_buf_t *)data);
722 }
723 }
724
725 /*===========================================================================
726 * FUNCTION : releaseJpegData
727 *
728 * DESCRIPTION: callback function to release jpeg job node
729 *
730 * PARAMETERS :
731 * @data : ptr to ongoing jpeg job data
732 * @user_data : user data ptr (QCamera3Reprocessor)
733 *
734 * RETURN : None
735 *==========================================================================*/
releaseJpegData(void * data,void * user_data)736 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data)
737 {
738 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
739 if (NULL != pme) {
740 pme->releaseJpegJobData((qcamera_hal3_jpeg_data_t *)data);
741 }
742 }
743
744 /*===========================================================================
745 * FUNCTION : releaseOngoingPPData
746 *
747 * DESCRIPTION: callback function to release ongoing postprocess job node
748 *
749 * PARAMETERS :
750 * @data : ptr to onging postprocess job
751 * @user_data : user data ptr (QCamera3Reprocessor)
752 *
753 * RETURN : None
754 *==========================================================================*/
releaseOngoingPPData(void * data,void * user_data)755 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data)
756 {
757 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
758 if (NULL != pme) {
759 qcamera_hal3_pp_data_t *pp_job = (qcamera_hal3_pp_data_t *)data;
760 if (NULL != pp_job->src_frame) {
761 pme->releaseSuperBuf(pp_job->src_frame);
762 free(pp_job->src_frame);
763 if (NULL != pp_job->src_metadata) {
764 pme->m_parent->metadataBufDone(pp_job->src_metadata);
765 free(pp_job->src_metadata);
766 }
767 pp_job->src_frame = NULL;
768 pp_job->metadata = NULL;
769 }
770
771 if (NULL != pp_job->fwk_src_frame) {
772 free(pp_job->fwk_src_frame);
773 pp_job->fwk_src_frame = NULL;
774 }
775 }
776 }
777
778 /*===========================================================================
779 * FUNCTION : releaseSuperBuf
780 *
781 * DESCRIPTION: function to release a superbuf frame by returning back to kernel
782 *
783 * PARAMETERS :
784 * @super_buf : ptr to the superbuf frame
785 *
786 * RETURN : None
787 *==========================================================================*/
releaseSuperBuf(mm_camera_super_buf_t * super_buf)788 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
789 {
790 if (NULL != super_buf) {
791 if (m_parent != NULL) {
792 m_parent->bufDone(super_buf);
793 }
794 }
795 }
796
797 /*===========================================================================
798 * FUNCTION : releaseOfflineBuffers
799 *
800 * DESCRIPTION: function to release/unmap offline buffers if any
801 *
802 * PARAMETERS : None
803 *
804 * RETURN : int32_t type of status
805 * NO_ERROR -- success
806 * none-zero failure code
807 *==========================================================================*/
releaseOfflineBuffers()808 int32_t QCamera3PostProcessor::releaseOfflineBuffers()
809 {
810 int32_t rc = NO_ERROR;
811
812 if(NULL != m_pReprocChannel) {
813 rc = m_pReprocChannel->unmapOfflineBuffers(false);
814 }
815
816 return rc;
817 }
818
819 /*===========================================================================
820 * FUNCTION : releaseJpegJobData
821 *
822 * DESCRIPTION: function to release internal resources in jpeg job struct
823 *
824 * PARAMETERS :
825 * @job : ptr to jpeg job struct
826 *
827 * RETURN : None
828 *
829 * NOTE : original source frame need to be queued back to kernel for
830 * future use. Output buf of jpeg job need to be released since
831 * it's allocated for each job. Exif object need to be deleted.
832 *==========================================================================*/
releaseJpegJobData(qcamera_hal3_jpeg_data_t * job)833 void QCamera3PostProcessor::releaseJpegJobData(qcamera_hal3_jpeg_data_t *job)
834 {
835 ATRACE_CALL();
836 int32_t rc = NO_ERROR;
837 CDBG("%s: E", __func__);
838 if (NULL != job) {
839 if (NULL != job->src_reproc_frame) {
840 free(job->src_reproc_frame);
841 job->src_reproc_frame = NULL;
842 }
843
844 if (NULL != job->src_frame) {
845 if (NULL != m_pReprocChannel) {
846 rc = m_pReprocChannel->bufDone(job->src_frame);
847 if (NO_ERROR != rc)
848 ALOGE("%s: bufDone error: %d", __func__, rc);
849 }
850 free(job->src_frame);
851 job->src_frame = NULL;
852 }
853
854 if (NULL != job->fwk_src_buffer) {
855 free(job->fwk_src_buffer);
856 job->fwk_src_buffer = NULL;
857 } else if (NULL != job->src_metadata) {
858 m_parent->metadataBufDone(job->src_metadata);
859 free(job->src_metadata);
860 job->src_metadata = NULL;
861 }
862
863 if (NULL != job->fwk_frame) {
864 free(job->fwk_frame);
865 job->fwk_frame = NULL;
866 }
867
868 if (NULL != job->pJpegExifObj) {
869 delete job->pJpegExifObj;
870 job->pJpegExifObj = NULL;
871 }
872
873 if (NULL != job->jpeg_settings) {
874 free(job->jpeg_settings);
875 job->jpeg_settings = NULL;
876 }
877 }
878 /* Additional trigger to process any pending jobs in the input queue */
879 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
880 CDBG("%s: X", __func__);
881 }
882
883 /*===========================================================================
884 * FUNCTION : getColorfmtFromImgFmt
885 *
886 * DESCRIPTION: function to return jpeg color format based on its image format
887 *
888 * PARAMETERS :
889 * @img_fmt : image format
890 *
891 * RETURN : jpeg color format that can be understandable by omx lib
892 *==========================================================================*/
getColorfmtFromImgFmt(cam_format_t img_fmt)893 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
894 {
895 switch (img_fmt) {
896 case CAM_FORMAT_YUV_420_NV21:
897 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
898 case CAM_FORMAT_YUV_420_NV21_ADRENO:
899 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
900 case CAM_FORMAT_YUV_420_NV12:
901 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
902 case CAM_FORMAT_YUV_420_YV12:
903 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
904 case CAM_FORMAT_YUV_422_NV61:
905 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
906 case CAM_FORMAT_YUV_422_NV16:
907 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
908 default:
909 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
910 }
911 }
912
913 /*===========================================================================
914 * FUNCTION : getJpegImgTypeFromImgFmt
915 *
916 * DESCRIPTION: function to return jpeg encode image type based on its image format
917 *
918 * PARAMETERS :
919 * @img_fmt : image format
920 *
921 * RETURN : return jpeg source image format (YUV or Bitstream)
922 *==========================================================================*/
getJpegImgTypeFromImgFmt(cam_format_t img_fmt)923 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
924 {
925 switch (img_fmt) {
926 case CAM_FORMAT_YUV_420_NV21:
927 case CAM_FORMAT_YUV_420_NV21_ADRENO:
928 case CAM_FORMAT_YUV_420_NV12:
929 case CAM_FORMAT_YUV_420_YV12:
930 case CAM_FORMAT_YUV_422_NV61:
931 case CAM_FORMAT_YUV_422_NV16:
932 return MM_JPEG_FMT_YUV;
933 default:
934 return MM_JPEG_FMT_YUV;
935 }
936 }
937
938 /*===========================================================================
939 * FUNCTION : encodeFWKData
940 *
941 * DESCRIPTION: function to prepare encoding job information and send to
942 * mm-jpeg-interface to do the encoding job
943 *
944 * PARAMETERS :
945 * @jpeg_job_data : ptr to a struct saving job related information
946 * @needNewSess : flag to indicate if a new jpeg encoding session need
947 * to be created. After creation, this flag will be toggled
948 *
949 * RETURN : int32_t type of status
950 * NO_ERROR -- success
951 * none-zero failure code
952 *==========================================================================*/
encodeFWKData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)953 int32_t QCamera3PostProcessor::encodeFWKData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
954 uint8_t &needNewSess)
955 {
956 CDBG("%s : E", __func__);
957 int32_t ret = NO_ERROR;
958 mm_jpeg_job_t jpg_job;
959 uint32_t jobId = 0;
960 qcamera_fwk_input_pp_data_t *recvd_frame = NULL;
961 metadata_buffer_t *metadata = NULL;
962 jpeg_settings_t *jpeg_settings = NULL;
963 QCamera3HardwareInterface* hal_obj = NULL;
964
965 if (NULL == jpeg_job_data) {
966 ALOGE("%s: Invalid jpeg job", __func__);
967 return BAD_VALUE;
968 }
969
970 recvd_frame = jpeg_job_data->fwk_frame;
971 if (NULL == recvd_frame) {
972 ALOGE("%s: Invalid input buffer", __func__);
973 return BAD_VALUE;
974 }
975
976 metadata = jpeg_job_data->metadata;
977 if (NULL == metadata) {
978 ALOGE("%s: Invalid metadata buffer", __func__);
979 return BAD_VALUE;
980 }
981
982 jpeg_settings = jpeg_job_data->jpeg_settings;
983 if (NULL == jpeg_settings) {
984 ALOGE("%s: Invalid jpeg settings buffer", __func__);
985 return BAD_VALUE;
986 }
987
988 if ((NULL != jpeg_job_data->src_frame) && (NULL != jpeg_job_data->src_frame)) {
989 ALOGE("%s: Unsupported case both framework and camera source buffers are invalid!",
990 __func__);
991 return BAD_VALUE;
992 }
993
994 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
995
996 if (mJpegClientHandle <= 0) {
997 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
998 return UNKNOWN_ERROR;
999 }
1000
1001 cam_dimension_t src_dim;
1002 memset(&src_dim, 0, sizeof(cam_dimension_t));
1003 src_dim.width = recvd_frame->reproc_config.input_stream_dim.width;
1004 src_dim.height = recvd_frame->reproc_config.input_stream_dim.height;
1005
1006 cam_dimension_t dst_dim;
1007 memset(&dst_dim, 0, sizeof(cam_dimension_t));
1008 dst_dim.width = recvd_frame->reproc_config.output_stream_dim.width;
1009 dst_dim.height = recvd_frame->reproc_config.output_stream_dim.height;
1010
1011 CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
1012 if (needNewSess) {
1013 //creating a new session, so we must destroy the old one
1014 if ( 0 < mJpegSessionId ) {
1015 ret = mJpegHandle.destroy_session(mJpegSessionId);
1016 if (ret != NO_ERROR) {
1017 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
1018 __func__, mJpegSessionId);
1019 return ret;
1020 }
1021 mJpegSessionId = 0;
1022 }
1023 // create jpeg encoding session
1024 mm_jpeg_encode_params_t encodeParam;
1025 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1026 encodeParam.main_dim.src_dim = src_dim;
1027 encodeParam.main_dim.dst_dim = dst_dim;
1028 encodeParam.thumb_dim.src_dim = src_dim;
1029 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1030
1031 getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings);
1032 CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
1033 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1034
1035 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1036 if (ret != NO_ERROR) {
1037 ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
1038 return ret;
1039 }
1040 needNewSess = FALSE;
1041 }
1042
1043 // Fill in new job
1044 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1045 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1046 jpg_job.encode_job.session_id = mJpegSessionId;
1047 jpg_job.encode_job.src_index = 0;
1048 jpg_job.encode_job.dst_index = 0;
1049
1050 cam_rect_t crop;
1051 memset(&crop, 0, sizeof(cam_rect_t));
1052 //TBD_later - Zoom event removed in stream
1053 //main_stream->getCropInfo(crop);
1054
1055 // main dim
1056 jpg_job.encode_job.main_dim.src_dim = src_dim;
1057 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1058 jpg_job.encode_job.main_dim.crop = crop;
1059
1060 // get exif data
1061 QCamera3Exif *pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings);
1062 jpeg_job_data->pJpegExifObj = pJpegExifObj;
1063 if (pJpegExifObj != NULL) {
1064 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1065 jpg_job.encode_job.exif_info.numOfEntries =
1066 pJpegExifObj->getNumOfEntries();
1067 }
1068
1069 // thumbnail dim
1070 CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
1071 if (m_bThumbnailNeeded == TRUE) {
1072 memset(&crop, 0, sizeof(cam_rect_t));
1073 jpg_job.encode_job.thumb_dim.dst_dim =
1074 jpeg_settings->thumbnail_size;
1075
1076 if (!hal_obj->needRotationReprocess()) {
1077 jpg_job.encode_job.rotation =
1078 jpeg_settings->jpeg_orientation;
1079 CDBG_HIGH("%s: jpeg rotation is set to %d", __func__,
1080 jpg_job.encode_job.rotation);
1081 } else if (jpeg_settings->jpeg_orientation == 90 ||
1082 jpeg_settings->jpeg_orientation == 270) {
1083 //swap the thumbnail destination width and height if it has
1084 //already been rotated
1085 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1086 jpg_job.encode_job.thumb_dim.dst_dim.width =
1087 jpg_job.encode_job.thumb_dim.dst_dim.height;
1088 jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1089 }
1090 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1091 jpg_job.encode_job.thumb_dim.crop = crop;
1092 jpg_job.encode_job.thumb_index = 0;
1093 }
1094
1095 if (metadata != NULL) {
1096 //Fill in the metadata passed as parameter
1097 jpg_job.encode_job.p_metadata = metadata;
1098 } else {
1099 ALOGE("%s: Metadata is null", __func__);
1100 }
1101
1102 jpg_job.encode_job.hal_version = CAM_HAL_V3;
1103
1104 //Start jpeg encoding
1105 ret = mJpegHandle.start_job(&jpg_job, &jobId);
1106 if (ret == NO_ERROR) {
1107 // remember job info
1108 jpeg_job_data->jobId = jobId;
1109 }
1110
1111 CDBG("%s : X", __func__);
1112 return ret;
1113 }
1114
1115 /*===========================================================================
1116 * FUNCTION : encodeData
1117 *
1118 * DESCRIPTION: function to prepare encoding job information and send to
1119 * mm-jpeg-interface to do the encoding job
1120 *
1121 * PARAMETERS :
1122 * @jpeg_job_data : ptr to a struct saving job related information
1123 * @needNewSess : flag to indicate if a new jpeg encoding session need
1124 * to be created. After creation, this flag will be toggled
1125 *
1126 * RETURN : int32_t type of status
1127 * NO_ERROR -- success
1128 * none-zero failure code
1129 *==========================================================================*/
encodeData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1130 int32_t QCamera3PostProcessor::encodeData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
1131 uint8_t &needNewSess)
1132 {
1133 ATRACE_CALL();
1134 CDBG("%s : E", __func__);
1135 int32_t ret = NO_ERROR;
1136 mm_jpeg_job_t jpg_job;
1137 uint32_t jobId = 0;
1138 QCamera3Stream *main_stream = NULL;
1139 mm_camera_buf_def_t *main_frame = NULL;
1140 QCamera3Channel *srcChannel = NULL;
1141 mm_camera_super_buf_t *recvd_frame = NULL;
1142 metadata_buffer_t *metadata = NULL;
1143 jpeg_settings_t *jpeg_settings = NULL;
1144 QCamera3HardwareInterface* hal_obj = NULL;
1145 bool needJpegRotation = false;
1146
1147 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1148 recvd_frame = jpeg_job_data->src_frame;
1149 metadata = jpeg_job_data->metadata;
1150 jpeg_settings = jpeg_job_data->jpeg_settings;
1151
1152 CDBG("%s: encoding bufIndex: %u", __func__,
1153 jpeg_job_data->src_frame->bufs[0]->buf_idx);
1154
1155 QCamera3Channel *pChannel = NULL;
1156 // first check picture channel
1157 if (m_parent != NULL &&
1158 m_parent->getMyHandle() == recvd_frame->ch_id) {
1159 pChannel = m_parent;
1160 }
1161 // check reprocess channel if not found
1162 if (pChannel == NULL) {
1163 if (m_pReprocChannel != NULL &&
1164 m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
1165 pChannel = m_pReprocChannel;
1166 }
1167 }
1168
1169 srcChannel = pChannel;
1170
1171 if (srcChannel == NULL) {
1172 ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here",
1173 __func__, recvd_frame->ch_id);
1174 return BAD_VALUE;
1175 }
1176
1177 // find snapshot frame and thumnail frame
1178 //Note: In this version we will receive only snapshot frame.
1179 for (int i = 0; i < recvd_frame->num_bufs; i++) {
1180 QCamera3Stream *srcStream =
1181 srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
1182 if (srcStream != NULL) {
1183 switch (srcStream->getMyType()) {
1184 case CAM_STREAM_TYPE_SNAPSHOT:
1185 case CAM_STREAM_TYPE_OFFLINE_PROC:
1186 main_stream = srcStream;
1187 main_frame = recvd_frame->bufs[i];
1188 break;
1189 default:
1190 break;
1191 }
1192 }
1193 }
1194
1195 if(NULL == main_frame){
1196 ALOGE("%s : Main frame is NULL", __func__);
1197 return BAD_VALUE;
1198 }
1199
1200 QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info;
1201 if (NULL == memObj) {
1202 ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
1203 return NO_MEMORY;
1204 }
1205
1206 // clean and invalidate cache ops through mem obj of the frame
1207 memObj->cleanInvalidateCache(main_frame->buf_idx);
1208
1209 if (mJpegClientHandle <= 0) {
1210 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
1211 return UNKNOWN_ERROR;
1212 }
1213 cam_dimension_t src_dim;
1214 memset(&src_dim, 0, sizeof(cam_dimension_t));
1215 main_stream->getFrameDimension(src_dim);
1216
1217 cam_dimension_t dst_dim;
1218 memset(&dst_dim, 0, sizeof(cam_dimension_t));
1219 srcChannel->getStreamByIndex(0)->getFrameDimension(dst_dim);
1220
1221 needJpegRotation = hal_obj->needJpegRotation();
1222 CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
1223 if (needNewSess) {
1224 //creating a new session, so we must destroy the old one
1225 if ( 0 < mJpegSessionId ) {
1226 ret = mJpegHandle.destroy_session(mJpegSessionId);
1227 if (ret != NO_ERROR) {
1228 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
1229 __func__, mJpegSessionId);
1230 return ret;
1231 }
1232 mJpegSessionId = 0;
1233 }
1234 // create jpeg encoding session
1235 mm_jpeg_encode_params_t encodeParam;
1236 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1237 getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings);
1238 CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
1239 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1240 if (!needJpegRotation &&
1241 (jpeg_settings->jpeg_orientation == 90 ||
1242 jpeg_settings->jpeg_orientation == 270)) {
1243 //swap src width and height, stride and scanline due to rotation
1244 encodeParam.main_dim.src_dim.width = src_dim.height;
1245 encodeParam.main_dim.src_dim.height = src_dim.width;
1246 encodeParam.thumb_dim.src_dim.width = src_dim.height;
1247 encodeParam.thumb_dim.src_dim.height = src_dim.width;
1248
1249 int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride;
1250 encodeParam.src_main_buf[0].offset.mp[0].stride =
1251 encodeParam.src_main_buf[0].offset.mp[0].scanline;
1252 encodeParam.src_main_buf[0].offset.mp[0].scanline = temp;
1253
1254 temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride;
1255 encodeParam.src_thumb_buf[0].offset.mp[0].stride =
1256 encodeParam.src_thumb_buf[0].offset.mp[0].scanline;
1257 encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp;
1258 } else {
1259 encodeParam.main_dim.src_dim = src_dim;
1260 encodeParam.thumb_dim.src_dim = src_dim;
1261 }
1262 encodeParam.main_dim.dst_dim = dst_dim;
1263 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1264 if (needJpegRotation) {
1265 encodeParam.rotation = jpeg_settings->jpeg_orientation;
1266 }
1267
1268
1269 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1270 if (ret != NO_ERROR) {
1271 ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
1272 return ret;
1273 }
1274 needNewSess = FALSE;
1275 }
1276
1277 // Fill in new job
1278 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1279 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1280 jpg_job.encode_job.session_id = mJpegSessionId;
1281 jpg_job.encode_job.src_index = main_frame->buf_idx;
1282 jpg_job.encode_job.dst_index = 0;
1283
1284 if (needJpegRotation) {
1285 jpg_job.encode_job.rotation =
1286 jpeg_settings->jpeg_orientation;
1287 CDBG("%s: %d: jpeg rotation is set to %d", __func__, __LINE__,
1288 jpg_job.encode_job.rotation);
1289 }
1290
1291 cam_rect_t crop;
1292 memset(&crop, 0, sizeof(cam_rect_t));
1293 //TBD_later - Zoom event removed in stream
1294 //main_stream->getCropInfo(crop);
1295
1296 // main dim
1297 jpg_job.encode_job.main_dim.src_dim = src_dim;
1298 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1299 jpg_job.encode_job.main_dim.crop = crop;
1300
1301 // get exif data
1302 QCamera3Exif *pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings);
1303 jpeg_job_data->pJpegExifObj = pJpegExifObj;
1304 if (pJpegExifObj != NULL) {
1305 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1306 jpg_job.encode_job.exif_info.numOfEntries =
1307 pJpegExifObj->getNumOfEntries();
1308 }
1309
1310 // thumbnail dim
1311 CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
1312 if (m_bThumbnailNeeded == TRUE) {
1313 memset(&crop, 0, sizeof(cam_rect_t));
1314 jpg_job.encode_job.thumb_dim.dst_dim =
1315 jpeg_settings->thumbnail_size;
1316
1317 if (!needJpegRotation &&
1318 (jpeg_settings->jpeg_orientation == 90 ||
1319 jpeg_settings->jpeg_orientation == 270)) {
1320 //swap the thumbnail destination width and height if it has
1321 //already been rotated
1322 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1323 jpg_job.encode_job.thumb_dim.dst_dim.width =
1324 jpg_job.encode_job.thumb_dim.dst_dim.height;
1325 jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1326
1327 jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height;
1328 jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width;
1329 } else {
1330 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1331 }
1332 jpg_job.encode_job.thumb_dim.crop = crop;
1333 jpg_job.encode_job.thumb_index = main_frame->buf_idx;
1334 }
1335
1336 if (metadata != NULL) {
1337 //Fill in the metadata passed as parameter
1338 jpg_job.encode_job.p_metadata = metadata;
1339 } else {
1340 ALOGE("%s: Metadata is null", __func__);
1341 }
1342
1343 jpg_job.encode_job.hal_version = CAM_HAL_V3;
1344
1345 //Start jpeg encoding
1346 ret = mJpegHandle.start_job(&jpg_job, &jobId);
1347 if (ret == NO_ERROR) {
1348 // remember job info
1349 jpeg_job_data->jobId = jobId;
1350 }
1351
1352 CDBG("%s : X", __func__);
1353 return ret;
1354 }
1355
1356 /*===========================================================================
1357 * FUNCTION : dataProcessRoutine
1358 *
1359 * DESCRIPTION: data process routine that handles input data either from input
1360 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do
1361 * reprocess.
1362 *
1363 * PARAMETERS :
1364 * @data : user data ptr (QCamera3PostProcessor)
1365 *
1366 * RETURN : None
1367 *==========================================================================*/
dataProcessRoutine(void * data)1368 void *QCamera3PostProcessor::dataProcessRoutine(void *data)
1369 {
1370 int running = 1;
1371 int ret;
1372 uint8_t is_active = FALSE;
1373 uint8_t needNewSess = TRUE;
1374 mm_camera_super_buf_t *meta_buffer = NULL;
1375 CDBG("%s: E", __func__);
1376 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
1377 QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
1378 cmdThread->setName("cam_data_proc");
1379
1380 do {
1381 do {
1382 ret = cam_sem_wait(&cmdThread->cmd_sem);
1383 if (ret != 0 && errno != EINVAL) {
1384 ALOGE("%s: cam_sem_wait error (%s)",
1385 __func__, strerror(errno));
1386 return NULL;
1387 }
1388 } while (ret != 0);
1389
1390 // we got notified about new cmd avail in cmd queue
1391 camera_cmd_type_t cmd = cmdThread->getCmd();
1392 switch (cmd) {
1393 case CAMERA_CMD_TYPE_START_DATA_PROC:
1394 CDBG_HIGH("%s: start data proc", __func__);
1395 is_active = TRUE;
1396 needNewSess = TRUE;
1397
1398 pme->m_ongoingPPQ.init();
1399 pme->m_inputJpegQ.init();
1400 pme->m_inputPPQ.init();
1401 pme->m_inputFWKPPQ.init();
1402 pme->m_inputRawQ.init();
1403 pme->m_inputMetaQ.init();
1404
1405 break;
1406 case CAMERA_CMD_TYPE_STOP_DATA_PROC:
1407 {
1408 CDBG_HIGH("%s: stop data proc", __func__);
1409 is_active = FALSE;
1410
1411 // cancel all ongoing jpeg jobs
1412 qcamera_hal3_jpeg_data_t *jpeg_job =
1413 (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1414 while (jpeg_job != NULL) {
1415 pme->mJpegHandle.abort_job(jpeg_job->jobId);
1416
1417 pme->releaseJpegJobData(jpeg_job);
1418 free(jpeg_job);
1419
1420 jpeg_job = (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1421 }
1422
1423 // destroy jpeg encoding session
1424 if ( 0 < pme->mJpegSessionId ) {
1425 pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
1426 pme->mJpegSessionId = 0;
1427 }
1428
1429 needNewSess = TRUE;
1430
1431 // flush ongoing postproc Queue
1432 pme->m_ongoingPPQ.flush();
1433
1434 // flush input jpeg Queue
1435 pme->m_inputJpegQ.flush();
1436
1437 // flush input Postproc Queue
1438 pme->m_inputPPQ.flush();
1439
1440 // flush framework input Postproc Queue
1441 pme->m_inputFWKPPQ.flush();
1442
1443 // flush input raw Queue
1444 pme->m_inputRawQ.flush();
1445
1446 pme->m_inputMetaQ.flush();
1447
1448 // signal cmd is completed
1449 cam_sem_post(&cmdThread->sync_sem);
1450 }
1451 break;
1452 case CAMERA_CMD_TYPE_DO_NEXT_JOB:
1453 {
1454 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
1455 /* needNewSess is set to TRUE as postproc is not re-STARTed
1456 * anymore for every captureRequest */
1457 needNewSess = TRUE;
1458 if (is_active == TRUE) {
1459 // check if there is any ongoing jpeg jobs
1460 if (pme->m_ongoingJpegQ.isEmpty()) {
1461 CDBG("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
1462 // no ongoing jpeg job, we are fine to send jpeg encoding job
1463 qcamera_hal3_jpeg_data_t *jpeg_job =
1464 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1465
1466 if (NULL != jpeg_job) {
1467 // add into ongoing jpeg job Q
1468 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
1469
1470 if (jpeg_job->fwk_frame) {
1471 ret = pme->encodeFWKData(jpeg_job, needNewSess);
1472 } else {
1473 ret = pme->encodeData(jpeg_job, needNewSess);
1474 }
1475 if (NO_ERROR != ret) {
1476 // dequeue the last one
1477 pme->m_ongoingJpegQ.dequeue(false);
1478
1479 pme->releaseJpegJobData(jpeg_job);
1480 free(jpeg_job);
1481 }
1482 }
1483 }
1484
1485 // check if there are any framework pp jobs
1486 if (!pme->m_inputFWKPPQ.isEmpty()) {
1487 qcamera_fwk_input_pp_data_t *fwk_frame =
1488 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
1489 if (NULL != fwk_frame) {
1490 qcamera_hal3_pp_data_t *pp_job =
1491 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
1492 jpeg_settings_t *jpeg_settings =
1493 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
1494 if (pp_job != NULL) {
1495 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
1496 pp_job->jpeg_settings = jpeg_settings;
1497 if (pme->m_pReprocChannel != NULL) {
1498 if (NO_ERROR != pme->m_pReprocChannel->extractCrop(fwk_frame)) {
1499 ALOGE("%s: Failed to extract output crop", __func__);
1500 }
1501 // add into ongoing PP job Q
1502 pp_job->fwk_src_frame = fwk_frame;
1503 pme->m_ongoingPPQ.enqueue((void *)pp_job);
1504 ret = pme->m_pReprocChannel->doReprocessOffline(fwk_frame);
1505 if (NO_ERROR != ret) {
1506 // remove from ongoing PP job Q
1507 pme->m_ongoingPPQ.dequeue(false);
1508 }
1509 } else {
1510 ALOGE("%s: Reprocess channel is NULL", __func__);
1511 ret = -1;
1512 }
1513 } else {
1514 ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__);
1515 ret = -1;
1516 }
1517
1518 if (0 != ret) {
1519 // free pp_job
1520 if (pp_job != NULL) {
1521 free(pp_job);
1522 }
1523 // free frame
1524 if (fwk_frame != NULL) {
1525 free(fwk_frame);
1526 }
1527 }
1528 }
1529 }
1530
1531 CDBG_HIGH("%s: dequeuing pp frame", __func__);
1532 pthread_mutex_lock(&pme->mReprocJobLock);
1533 if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) {
1534 mm_camera_super_buf_t *pp_frame =
1535 (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
1536 meta_buffer =
1537 (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
1538 jpeg_settings_t *jpeg_settings =
1539 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
1540 pthread_mutex_unlock(&pme->mReprocJobLock);
1541 qcamera_hal3_pp_data_t *pp_job =
1542 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
1543 if (pp_job != NULL) {
1544 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
1545 pp_job->src_frame = pp_frame;
1546 pp_job->src_metadata = meta_buffer;
1547 pp_job->metadata =
1548 (metadata_buffer_t *)meta_buffer->bufs[0]->buffer;
1549 pp_job->jpeg_settings = jpeg_settings;
1550 pme->m_ongoingPPQ.enqueue((void *)pp_job);
1551 if (pme->m_pReprocChannel != NULL) {
1552 qcamera_fwk_input_pp_data_t fwk_frame;
1553 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
1554 ret = pme->m_pReprocChannel->extractFrameCropAndRotation(
1555 pp_frame, meta_buffer->bufs[0],
1556 pp_job->jpeg_settings,
1557 fwk_frame);
1558 if (NO_ERROR == ret) {
1559 // add into ongoing PP job Q
1560 ret = pme->m_pReprocChannel->doReprocessOffline(
1561 &fwk_frame);
1562 if (NO_ERROR != ret) {
1563 // remove from ongoing PP job Q
1564 pme->m_ongoingPPQ.dequeue(false);
1565 }
1566 }
1567 } else {
1568 CDBG_HIGH("%s: No reprocess. Calling processPPData directly",
1569 __func__);
1570 ret = pme->processPPData(pp_frame);
1571 }
1572 } else {
1573 ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__);
1574 ret = -1;
1575 }
1576
1577 if (0 != ret) {
1578 // free pp_job
1579 if (pp_job != NULL) {
1580 free(pp_job);
1581 }
1582 // free frame
1583 if (pp_frame != NULL) {
1584 pme->releaseSuperBuf(pp_frame);
1585 free(pp_frame);
1586 }
1587 //free metadata
1588 if (NULL != meta_buffer) {
1589 pme->m_parent->metadataBufDone(meta_buffer);
1590 free(meta_buffer);
1591 }
1592 }
1593 } else {
1594 pthread_mutex_unlock(&pme->mReprocJobLock);
1595 }
1596 } else {
1597 // not active, simply return buf and do no op
1598 qcamera_hal3_jpeg_data_t *jpeg_job =
1599 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1600 if (NULL != jpeg_job) {
1601 free(jpeg_job);
1602 }
1603 mm_camera_super_buf_t *super_buf;
1604 super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
1605 if (NULL != super_buf) {
1606 pme->releaseSuperBuf(super_buf);
1607 free(super_buf);
1608 }
1609 super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
1610 if (NULL != super_buf) {
1611 pme->releaseSuperBuf(super_buf);
1612 free(super_buf);
1613 }
1614 mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
1615 if (metadata != NULL) {
1616 pme->m_parent->metadataBufDone(metadata);
1617 free(metadata);
1618 }
1619 qcamera_fwk_input_pp_data_t *fwk_frame =
1620 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
1621 if (NULL != fwk_frame) {
1622 free(fwk_frame);
1623 }
1624 }
1625 }
1626 break;
1627 case CAMERA_CMD_TYPE_EXIT:
1628 running = 0;
1629 break;
1630 default:
1631 break;
1632 }
1633 } while (running);
1634 CDBG("%s: X", __func__);
1635 return NULL;
1636 }
1637
1638 /*===========================================================================
1639 * FUNCTION : QCamera3Exif
1640 *
1641 * DESCRIPTION: constructor of QCamera3Exif
1642 *
1643 * PARAMETERS : None
1644 *
1645 * RETURN : None
1646 *==========================================================================*/
QCamera3Exif()1647 QCamera3Exif::QCamera3Exif()
1648 : m_nNumEntries(0)
1649 {
1650 memset(m_Entries, 0, sizeof(m_Entries));
1651 }
1652
1653 /*===========================================================================
1654 * FUNCTION : ~QCamera3Exif
1655 *
1656 * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
1657 *
1658 * PARAMETERS : None
1659 *
1660 * RETURN : None
1661 *==========================================================================*/
~QCamera3Exif()1662 QCamera3Exif::~QCamera3Exif()
1663 {
1664 for (uint32_t i = 0; i < m_nNumEntries; i++) {
1665 switch (m_Entries[i].tag_entry.type) {
1666 case EXIF_BYTE:
1667 {
1668 if (m_Entries[i].tag_entry.count > 1 &&
1669 m_Entries[i].tag_entry.data._bytes != NULL) {
1670 free(m_Entries[i].tag_entry.data._bytes);
1671 m_Entries[i].tag_entry.data._bytes = NULL;
1672 }
1673 }
1674 break;
1675 case EXIF_ASCII:
1676 {
1677 if (m_Entries[i].tag_entry.data._ascii != NULL) {
1678 free(m_Entries[i].tag_entry.data._ascii);
1679 m_Entries[i].tag_entry.data._ascii = NULL;
1680 }
1681 }
1682 break;
1683 case EXIF_SHORT:
1684 {
1685 if (m_Entries[i].tag_entry.count > 1 &&
1686 m_Entries[i].tag_entry.data._shorts != NULL) {
1687 free(m_Entries[i].tag_entry.data._shorts);
1688 m_Entries[i].tag_entry.data._shorts = NULL;
1689 }
1690 }
1691 break;
1692 case EXIF_LONG:
1693 {
1694 if (m_Entries[i].tag_entry.count > 1 &&
1695 m_Entries[i].tag_entry.data._longs != NULL) {
1696 free(m_Entries[i].tag_entry.data._longs);
1697 m_Entries[i].tag_entry.data._longs = NULL;
1698 }
1699 }
1700 break;
1701 case EXIF_RATIONAL:
1702 {
1703 if (m_Entries[i].tag_entry.count > 1 &&
1704 m_Entries[i].tag_entry.data._rats != NULL) {
1705 free(m_Entries[i].tag_entry.data._rats);
1706 m_Entries[i].tag_entry.data._rats = NULL;
1707 }
1708 }
1709 break;
1710 case EXIF_UNDEFINED:
1711 {
1712 if (m_Entries[i].tag_entry.data._undefined != NULL) {
1713 free(m_Entries[i].tag_entry.data._undefined);
1714 m_Entries[i].tag_entry.data._undefined = NULL;
1715 }
1716 }
1717 break;
1718 case EXIF_SLONG:
1719 {
1720 if (m_Entries[i].tag_entry.count > 1 &&
1721 m_Entries[i].tag_entry.data._slongs != NULL) {
1722 free(m_Entries[i].tag_entry.data._slongs);
1723 m_Entries[i].tag_entry.data._slongs = NULL;
1724 }
1725 }
1726 break;
1727 case EXIF_SRATIONAL:
1728 {
1729 if (m_Entries[i].tag_entry.count > 1 &&
1730 m_Entries[i].tag_entry.data._srats != NULL) {
1731 free(m_Entries[i].tag_entry.data._srats);
1732 m_Entries[i].tag_entry.data._srats = NULL;
1733 }
1734 }
1735 break;
1736 default:
1737 ALOGE("%s: Error, Unknown type",__func__);
1738 break;
1739 }
1740 }
1741 }
1742
1743 /*===========================================================================
1744 * FUNCTION : addEntry
1745 *
1746 * DESCRIPTION: function to add an entry to exif data
1747 *
1748 * PARAMETERS :
1749 * @tagid : exif tag ID
1750 * @type : data type
1751 * @count : number of data in uint of its type
1752 * @data : input data ptr
1753 *
1754 * RETURN : int32_t type of status
1755 * NO_ERROR -- success
1756 * none-zero failure code
1757 *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)1758 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
1759 exif_tag_type_t type,
1760 uint32_t count,
1761 void *data)
1762 {
1763 int32_t rc = NO_ERROR;
1764 if(m_nNumEntries >= MAX_HAL3_EXIF_TABLE_ENTRIES) {
1765 ALOGE("%s: Number of entries exceeded limit", __func__);
1766 return NO_MEMORY;
1767 }
1768
1769 m_Entries[m_nNumEntries].tag_id = tagid;
1770 m_Entries[m_nNumEntries].tag_entry.type = type;
1771 m_Entries[m_nNumEntries].tag_entry.count = count;
1772 m_Entries[m_nNumEntries].tag_entry.copy = 1;
1773 switch (type) {
1774 case EXIF_BYTE:
1775 {
1776 if (count > 1) {
1777 uint8_t *values = (uint8_t *)malloc(count);
1778 if (values == NULL) {
1779 ALOGE("%s: No memory for byte array", __func__);
1780 rc = NO_MEMORY;
1781 } else {
1782 memcpy(values, data, count);
1783 m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
1784 }
1785 } else {
1786 m_Entries[m_nNumEntries].tag_entry.data._byte =
1787 *(uint8_t *)data;
1788 }
1789 }
1790 break;
1791 case EXIF_ASCII:
1792 {
1793 char *str = NULL;
1794 str = (char *)malloc(count + 1);
1795 if (str == NULL) {
1796 ALOGE("%s: No memory for ascii string", __func__);
1797 rc = NO_MEMORY;
1798 } else {
1799 memset(str, 0, count + 1);
1800 memcpy(str, data, count);
1801 m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
1802 }
1803 }
1804 break;
1805 case EXIF_SHORT:
1806 {
1807 if (count > 1) {
1808 uint16_t *values =
1809 (uint16_t *)malloc(count * sizeof(uint16_t));
1810 if (values == NULL) {
1811 ALOGE("%s: No memory for short array", __func__);
1812 rc = NO_MEMORY;
1813 } else {
1814 memcpy(values, data, count * sizeof(uint16_t));
1815 m_Entries[m_nNumEntries].tag_entry.data._shorts =values;
1816 }
1817 } else {
1818 m_Entries[m_nNumEntries].tag_entry.data._short =
1819 *(uint16_t *)data;
1820 }
1821 }
1822 break;
1823 case EXIF_LONG:
1824 {
1825 if (count > 1) {
1826 uint32_t *values =
1827 (uint32_t *)malloc(count * sizeof(uint32_t));
1828 if (values == NULL) {
1829 ALOGE("%s: No memory for long array", __func__);
1830 rc = NO_MEMORY;
1831 } else {
1832 memcpy(values, data, count * sizeof(uint32_t));
1833 m_Entries[m_nNumEntries].tag_entry.data._longs = values;
1834 }
1835 } else {
1836 m_Entries[m_nNumEntries].tag_entry.data._long =
1837 *(uint32_t *)data;
1838 }
1839 }
1840 break;
1841 case EXIF_RATIONAL:
1842 {
1843 if (count > 1) {
1844 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
1845 if (values == NULL) {
1846 ALOGE("%s: No memory for rational array", __func__);
1847 rc = NO_MEMORY;
1848 } else {
1849 memcpy(values, data, count * sizeof(rat_t));
1850 m_Entries[m_nNumEntries].tag_entry.data._rats = values;
1851 }
1852 } else {
1853 m_Entries[m_nNumEntries].tag_entry.data._rat =
1854 *(rat_t *)data;
1855 }
1856 }
1857 break;
1858 case EXIF_UNDEFINED:
1859 {
1860 uint8_t *values = (uint8_t *)malloc(count);
1861 if (values == NULL) {
1862 ALOGE("%s: No memory for undefined array", __func__);
1863 rc = NO_MEMORY;
1864 } else {
1865 memcpy(values, data, count);
1866 m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
1867 }
1868 }
1869 break;
1870 case EXIF_SLONG:
1871 {
1872 if (count > 1) {
1873 int32_t *values =
1874 (int32_t *)malloc(count * sizeof(int32_t));
1875 if (values == NULL) {
1876 ALOGE("%s: No memory for signed long array", __func__);
1877 rc = NO_MEMORY;
1878 } else {
1879 memcpy(values, data, count * sizeof(int32_t));
1880 m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
1881 }
1882 } else {
1883 m_Entries[m_nNumEntries].tag_entry.data._slong =
1884 *(int32_t *)data;
1885 }
1886 }
1887 break;
1888 case EXIF_SRATIONAL:
1889 {
1890 if (count > 1) {
1891 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
1892 if (values == NULL) {
1893 ALOGE("%s: No memory for sign rational array",__func__);
1894 rc = NO_MEMORY;
1895 } else {
1896 memcpy(values, data, count * sizeof(srat_t));
1897 m_Entries[m_nNumEntries].tag_entry.data._srats = values;
1898 }
1899 } else {
1900 m_Entries[m_nNumEntries].tag_entry.data._srat =
1901 *(srat_t *)data;
1902 }
1903 }
1904 break;
1905 default:
1906 ALOGE("%s: Error, Unknown type",__func__);
1907 break;
1908 }
1909
1910 // Increase number of entries
1911 m_nNumEntries++;
1912 return rc;
1913 }
1914
1915 }; // namespace qcamera
1916