1 /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30 #define LOG_TAG "QCamera3PostProc"
31
32 // To remove
33 #include <cutils/properties.h>
34
35 // System dependencies
36 #include <stdio.h>
37
38 // Camera dependencies
39 #include "QCamera3Channel.h"
40 #include "QCamera3HWI.h"
41 #include "QCamera3PostProc.h"
42 #include "QCamera3Stream.h"
43 #include "QCameraTrace.h"
44
45 extern "C" {
46 #include "mm_camera_dbg.h"
47 }
48
49
50 namespace qcamera {
51
52 static const char ExifAsciiPrefix[] =
53 { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; // "ASCII\0\0\0"
54
55 __unused
56 static const char ExifUndefinedPrefix[] =
57 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // "\0\0\0\0\0\0\0\0"
58
59 #define EXIF_ASCII_PREFIX_SIZE 8 //(sizeof(ExifAsciiPrefix))
60 #define FOCAL_LENGTH_DECIMAL_PRECISION 1000
61
62 /*===========================================================================
63 * FUNCTION : QCamera3PostProcessor
64 *
65 * DESCRIPTION: constructor of QCamera3PostProcessor.
66 *
67 * PARAMETERS :
68 * @cam_ctrl : ptr to HWI object
69 *
70 * RETURN : None
71 *==========================================================================*/
QCamera3PostProcessor(QCamera3ProcessingChannel * ch_ctrl)72 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3ProcessingChannel* ch_ctrl)
73 : m_parent(ch_ctrl),
74 mJpegCB(NULL),
75 mJpegUserData(NULL),
76 mJpegClientHandle(0),
77 mJpegSessionId(0),
78 m_bThumbnailNeeded(TRUE),
79 m_pReprocChannel(NULL),
80 m_inputPPQ(releasePPInputData, this),
81 m_inputFWKPPQ(NULL, this),
82 m_ongoingPPQ(releaseOngoingPPData, this),
83 m_inputJpegQ(releaseJpegData, this),
84 m_ongoingJpegQ(releaseJpegData, this),
85 m_inputMetaQ(releaseMetadata, this),
86 m_jpegSettingsQ(NULL, this)
87 {
88 memset(&mJpegHandle, 0, sizeof(mJpegHandle));
89 memset(&mJpegMetadata, 0, sizeof(mJpegMetadata));
90 pthread_mutex_init(&mReprocJobLock, NULL);
91 }
92
93 /*===========================================================================
94 * FUNCTION : ~QCamera3PostProcessor
95 *
96 * DESCRIPTION: deconstructor of QCamera3PostProcessor.
97 *
98 * PARAMETERS : None
99 *
100 * RETURN : None
101 *==========================================================================*/
~QCamera3PostProcessor()102 QCamera3PostProcessor::~QCamera3PostProcessor()
103 {
104 pthread_mutex_destroy(&mReprocJobLock);
105 }
106
107 /*===========================================================================
108 * FUNCTION : init
109 *
110 * DESCRIPTION: initialization of postprocessor
111 *
112 * PARAMETERS :
113 * @memory : output buffer memory
114 *
115 * RETURN : int32_t type of status
116 * NO_ERROR -- success
117 * none-zero failure code
118 *==========================================================================*/
init(QCamera3StreamMem * memory)119 int32_t QCamera3PostProcessor::init(QCamera3StreamMem *memory)
120 {
121 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PPROC_INIT);
122 mOutputMem = memory;
123 m_dataProcTh.launch(dataProcessRoutine, this);
124
125 return NO_ERROR;
126 }
127
128 /*===========================================================================
129 * FUNCTION : deinit
130 *
131 * DESCRIPTION: de-initialization of postprocessor
132 *
133 * PARAMETERS : None
134 *
135 * RETURN : int32_t type of status
136 * NO_ERROR -- success
137 * none-zero failure code
138 *==========================================================================*/
deinit()139 int32_t QCamera3PostProcessor::deinit()
140 {
141 int rc = NO_ERROR;
142 m_dataProcTh.exit();
143
144 if (m_pReprocChannel != NULL) {
145 m_pReprocChannel->stop();
146 delete m_pReprocChannel;
147 m_pReprocChannel = NULL;
148 }
149
150 if(mJpegClientHandle > 0) {
151 rc = mJpegHandle.close(mJpegClientHandle);
152 LOGH("Jpeg closed, rc = %d, mJpegClientHandle = %x",
153 rc, mJpegClientHandle);
154 mJpegClientHandle = 0;
155 memset(&mJpegHandle, 0, sizeof(mJpegHandle));
156 }
157
158 mOutputMem = NULL;
159 return rc;
160 }
161
162 /*===========================================================================
163 * FUNCTION : initJpeg
164 *
165 * DESCRIPTION: initialization of jpeg through postprocessor
166 *
167 * PARAMETERS :
168 * @jpeg_cb : callback to handle jpeg event from mm-camera-interface
169 * @max_pic_dim : max picture dimensions
170 * @user_data : user data ptr for jpeg callback
171 *
172 * RETURN : int32_t type of status
173 * NO_ERROR -- success
174 * none-zero failure code
175 *==========================================================================*/
initJpeg(jpeg_encode_callback_t jpeg_cb,cam_dimension_t * max_pic_dim,void * user_data)176 int32_t QCamera3PostProcessor::initJpeg(jpeg_encode_callback_t jpeg_cb,
177 cam_dimension_t* max_pic_dim,
178 void *user_data)
179 {
180 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PPROC_INIT_JPEG);
181 mJpegCB = jpeg_cb;
182 mJpegUserData = user_data;
183 mm_dimension max_size;
184
185 if ((0 > max_pic_dim->width) || (0 > max_pic_dim->height)) {
186 LOGE("Negative dimension %dx%d",
187 max_pic_dim->width, max_pic_dim->height);
188 return BAD_VALUE;
189 }
190
191 // set max pic size
192 memset(&max_size, 0, sizeof(mm_dimension));
193 max_size.w = max_pic_dim->width;
194 max_size.h = max_pic_dim->height;
195
196 // Pass OTP calibration data to JPEG
197 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
198 mJpegMetadata.default_sensor_flip = FLIP_NONE;
199 mJpegMetadata.sensor_mount_angle = hal_obj->getSensorMountAngle();
200 memcpy(&mJpegMetadata.otp_calibration_data,
201 hal_obj->getRelatedCalibrationData(),
202 sizeof(cam_related_system_calibration_data_t));
203 mJpegClientHandle = jpeg_open(&mJpegHandle, NULL, max_size, &mJpegMetadata);
204
205 if (!mJpegClientHandle) {
206 LOGE("jpeg_open did not work");
207 return UNKNOWN_ERROR;
208 }
209 return NO_ERROR;
210 }
211
212 /*===========================================================================
213 * FUNCTION : start
214 *
215 * DESCRIPTION: start postprocessor. Data process thread and data notify thread
216 * will be launched.
217 *
218 * PARAMETERS :
219 * @config : reprocess configuration
220 *
221 * RETURN : int32_t type of status
222 * NO_ERROR -- success
223 * none-zero failure code
224 *
225 * NOTE : if any reprocess is needed, a reprocess channel/stream
226 * will be started.
227 *==========================================================================*/
start(const reprocess_config_t & config)228 int32_t QCamera3PostProcessor::start(const reprocess_config_t &config)
229 {
230 int32_t rc = NO_ERROR;
231 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
232
233 if (config.reprocess_type != REPROCESS_TYPE_NONE) {
234 if (m_pReprocChannel != NULL) {
235 m_pReprocChannel->stop();
236 delete m_pReprocChannel;
237 m_pReprocChannel = NULL;
238 }
239
240 // if reprocess is needed, start reprocess channel
241 LOGD("Setting input channel as pInputChannel");
242 m_pReprocChannel = hal_obj->addOfflineReprocChannel(config, m_parent);
243 if (m_pReprocChannel == NULL) {
244 LOGE("cannot add reprocess channel");
245 return UNKNOWN_ERROR;
246 }
247 /*start the reprocess channel only if buffers are already allocated, thus
248 only start it in an intermediate reprocess type, defer it for others*/
249 if (config.reprocess_type == REPROCESS_TYPE_JPEG) {
250 rc = m_pReprocChannel->start();
251 if (rc != 0) {
252 LOGE("cannot start reprocess channel");
253 delete m_pReprocChannel;
254 m_pReprocChannel = NULL;
255 return rc;
256 }
257 }
258 }
259 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, TRUE, FALSE);
260
261 return rc;
262 }
263
264 /*===========================================================================
265 * FUNCTION : flush
266 *
267 * DESCRIPTION: stop ongoing postprocess and jpeg jobs
268 *
269 * PARAMETERS : None
270 *
271 * RETURN : int32_t type of status
272 * NO_ERROR -- success
273 * none-zero failure code
274 *
275 *==========================================================================*/
flush()276 int32_t QCamera3PostProcessor::flush()
277 {
278 int32_t rc = NO_ERROR;
279 qcamera_hal3_jpeg_data_t *jpeg_job =
280 (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
281 while (jpeg_job != NULL) {
282 rc = mJpegHandle.abort_job(jpeg_job->jobId);
283 releaseJpegJobData(jpeg_job);
284 free(jpeg_job);
285
286 jpeg_job = (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
287 }
288 rc = releaseOfflineBuffers(true);
289 return rc;
290 }
291
292 /*===========================================================================
293 * FUNCTION : stop
294 *
295 * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
296 *
297 * PARAMETERS : None
298 *
299 * RETURN : int32_t type of status
300 * NO_ERROR -- success
301 * none-zero failure code
302 *
303 * NOTE : reprocess channel will be stopped and deleted if there is any
304 *==========================================================================*/
stop()305 int32_t QCamera3PostProcessor::stop()
306 {
307 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
308
309 if (m_pReprocChannel != NULL) {
310 m_pReprocChannel->stop();
311 delete m_pReprocChannel;
312 m_pReprocChannel = NULL;
313 }
314
315 return NO_ERROR;
316 }
317
318 /*===========================================================================
319 * FUNCTION : getFWKJpegEncodeConfig
320 *
321 * DESCRIPTION: function to prepare encoding job information
322 *
323 * PARAMETERS :
324 * @encode_parm : param to be filled with encoding configuration
325 * @frame : framework input buffer
326 * @jpeg_settings : jpeg settings to be applied for encoding
327 *
328 * RETURN : int32_t type of status
329 * NO_ERROR -- success
330 * none-zero failure code
331 *==========================================================================*/
getFWKJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,qcamera_fwk_input_pp_data_t * frame,jpeg_settings_t * jpeg_settings)332 int32_t QCamera3PostProcessor::getFWKJpegEncodeConfig(
333 mm_jpeg_encode_params_t& encode_parm,
334 qcamera_fwk_input_pp_data_t *frame,
335 jpeg_settings_t *jpeg_settings)
336 {
337 LOGD("E");
338 int32_t ret = NO_ERROR;
339
340 if ((NULL == frame) || (NULL == jpeg_settings)) {
341 return BAD_VALUE;
342 }
343
344 ssize_t bufSize = mOutputMem->getSize(jpeg_settings->out_buf_index);
345 if (BAD_INDEX == bufSize) {
346 LOGE("cannot retrieve buffer size for buffer %u",
347 jpeg_settings->out_buf_index);
348 return BAD_VALUE;
349 }
350
351 encode_parm.jpeg_cb = mJpegCB;
352 encode_parm.userdata = mJpegUserData;
353
354 if (jpeg_settings->thumbnail_size.width > 0 &&
355 jpeg_settings->thumbnail_size.height > 0)
356 m_bThumbnailNeeded = TRUE;
357 else
358 m_bThumbnailNeeded = FALSE;
359 encode_parm.encode_thumbnail = m_bThumbnailNeeded;
360
361 // get color format
362 cam_format_t img_fmt = frame->reproc_config.stream_format;
363 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
364
365 // get jpeg quality
366 encode_parm.quality = jpeg_settings->jpeg_quality;
367 if (encode_parm.quality <= 0) {
368 encode_parm.quality = 85;
369 }
370
371 // get jpeg thumbnail quality
372 encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
373
374 cam_frame_len_offset_t main_offset =
375 frame->reproc_config.input_stream_plane_info.plane_info;
376
377 encode_parm.num_src_bufs = 1;
378 encode_parm.src_main_buf[0].index = 0;
379 encode_parm.src_main_buf[0].buf_size = frame->input_buffer.frame_len;
380 encode_parm.src_main_buf[0].buf_vaddr = (uint8_t *) frame->input_buffer.buffer;
381 encode_parm.src_main_buf[0].fd = frame->input_buffer.fd;
382 encode_parm.src_main_buf[0].format = MM_JPEG_FMT_YUV;
383 encode_parm.src_main_buf[0].offset = main_offset;
384
385 //Pass input thumbnail buffer info to encoder.
386 //Note: Use main buffer to encode thumbnail
387 if (m_bThumbnailNeeded == TRUE) {
388 encode_parm.num_tmb_bufs = 1;
389 encode_parm.src_thumb_buf[0] = encode_parm.src_main_buf[0];
390 }
391
392 //Pass output jpeg buffer info to encoder.
393 //mOutputMem is allocated by framework.
394 encode_parm.num_dst_bufs = 1;
395 encode_parm.dest_buf[0].index = 0;
396 encode_parm.dest_buf[0].buf_size = (size_t)bufSize;
397 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mOutputMem->getPtr(
398 jpeg_settings->out_buf_index);
399 encode_parm.dest_buf[0].fd = mOutputMem->getFd(
400 jpeg_settings->out_buf_index);
401 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
402 encode_parm.dest_buf[0].offset = main_offset;
403
404 LOGD("X");
405 return NO_ERROR;
406
407 LOGD("X with error %d", ret);
408 return ret;
409 }
410
411 /*===========================================================================
412 * FUNCTION : getJpegEncodeConfig
413 *
414 * DESCRIPTION: function to prepare encoding job information
415 *
416 * PARAMETERS :
417 * @encode_parm : param to be filled with encoding configuration
418 * #main_stream : stream object where the input buffer comes from
419 * @jpeg_settings : jpeg settings to be applied for encoding
420 *
421 * RETURN : int32_t type of status
422 * NO_ERROR -- success
423 * none-zero failure code
424 *==========================================================================*/
getJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,QCamera3Stream * main_stream,jpeg_settings_t * jpeg_settings)425 int32_t QCamera3PostProcessor::getJpegEncodeConfig(
426 mm_jpeg_encode_params_t& encode_parm,
427 QCamera3Stream *main_stream,
428 jpeg_settings_t *jpeg_settings)
429 {
430 LOGD("E");
431 int32_t ret = NO_ERROR;
432 ssize_t bufSize = 0;
433
434 encode_parm.jpeg_cb = mJpegCB;
435 encode_parm.userdata = mJpegUserData;
436
437 if (jpeg_settings->thumbnail_size.width > 0 &&
438 jpeg_settings->thumbnail_size.height > 0)
439 m_bThumbnailNeeded = TRUE;
440 else
441 m_bThumbnailNeeded = FALSE;
442 encode_parm.encode_thumbnail = m_bThumbnailNeeded;
443
444 // get color format
445 cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12; //default value
446 main_stream->getFormat(img_fmt);
447 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
448
449 // get jpeg quality
450 encode_parm.quality = jpeg_settings->jpeg_quality;
451 if (encode_parm.quality <= 0) {
452 encode_parm.quality = 85;
453 }
454
455 // get jpeg thumbnail quality
456 encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
457
458 cam_frame_len_offset_t main_offset;
459 memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
460 main_stream->getFrameOffset(main_offset);
461
462 // src buf config
463 //Pass input main image buffer info to encoder.
464 QCamera3StreamMem *pStreamMem = main_stream->getStreamBufs();
465 if (pStreamMem == NULL) {
466 LOGE("cannot get stream bufs from main stream");
467 ret = BAD_VALUE;
468 goto on_error;
469 }
470 encode_parm.num_src_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
471 for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
472 if (pStreamMem != NULL) {
473 encode_parm.src_main_buf[i].index = i;
474 bufSize = pStreamMem->getSize(i);
475 if (BAD_INDEX == bufSize) {
476 LOGE("cannot retrieve buffer size for buffer %u", i);
477 ret = BAD_VALUE;
478 goto on_error;
479 }
480 encode_parm.src_main_buf[i].buf_size = (size_t)bufSize;
481 encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
482 encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
483 encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
484 encode_parm.src_main_buf[i].offset = main_offset;
485 }
486 }
487
488 //Pass input thumbnail buffer info to encoder.
489 //Note: Use main buffer to encode thumbnail
490 if (m_bThumbnailNeeded == TRUE) {
491 pStreamMem = main_stream->getStreamBufs();
492 if (pStreamMem == NULL) {
493 LOGE("cannot get stream bufs from thumb stream");
494 ret = BAD_VALUE;
495 goto on_error;
496 }
497 cam_frame_len_offset_t thumb_offset;
498 memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
499 main_stream->getFrameOffset(thumb_offset);
500 encode_parm.num_tmb_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
501 for (uint32_t i = 0; i < encode_parm.num_tmb_bufs; i++) {
502 if (pStreamMem != NULL) {
503 encode_parm.src_thumb_buf[i].index = i;
504 bufSize = pStreamMem->getSize(i);
505 if (BAD_INDEX == bufSize) {
506 LOGE("cannot retrieve buffer size for buffer %u", i);
507 ret = BAD_VALUE;
508 goto on_error;
509 }
510 encode_parm.src_thumb_buf[i].buf_size = (uint32_t)bufSize;
511 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
512 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
513 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
514 encode_parm.src_thumb_buf[i].offset = thumb_offset;
515 }
516 }
517 }
518
519 //Pass output jpeg buffer info to encoder.
520 //mJpegMem is allocated by framework.
521 bufSize = mOutputMem->getSize(jpeg_settings->out_buf_index);
522 if (BAD_INDEX == bufSize) {
523 LOGE("cannot retrieve buffer size for buffer %u",
524 jpeg_settings->out_buf_index);
525 ret = BAD_VALUE;
526 goto on_error;
527 }
528 encode_parm.num_dst_bufs = 1;
529 encode_parm.dest_buf[0].index = 0;
530 encode_parm.dest_buf[0].buf_size = (size_t)bufSize;
531 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mOutputMem->getPtr(
532 jpeg_settings->out_buf_index);
533 encode_parm.dest_buf[0].fd = mOutputMem->getFd(
534 jpeg_settings->out_buf_index);
535 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
536 encode_parm.dest_buf[0].offset = main_offset;
537
538 LOGD("X");
539 return NO_ERROR;
540
541 on_error:
542 LOGD("X with error %d", ret);
543 return ret;
544 }
545
processData(mm_camera_super_buf_t * input)546 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *input) {
547 return processData(input, NULL, 0);
548 }
549
550 /*===========================================================================
551 * FUNCTION : processData
552 *
553 * DESCRIPTION: enqueue data into dataProc thread
554 *
555 * PARAMETERS :
556 * @frame : process input frame
557 * @output : process output frame
558 *
559 * RETURN : int32_t type of status
560 * NO_ERROR -- success
561 * none-zero failure code
562 *
563 * NOTE : depends on if offline reprocess is needed, received frame will
564 * be sent to either input queue of postprocess or jpeg encoding
565 *==========================================================================*/
processData(mm_camera_super_buf_t * input,buffer_handle_t * output,uint32_t frameNumber)566 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *input,
567 buffer_handle_t *output, uint32_t frameNumber)
568 {
569 LOGD("E");
570 pthread_mutex_lock(&mReprocJobLock);
571
572 // enqueue to post proc input queue
573 qcamera_hal3_pp_buffer_t *pp_buffer = (qcamera_hal3_pp_buffer_t *)malloc(
574 sizeof(qcamera_hal3_pp_buffer_t));
575 if (NULL == pp_buffer) {
576 LOGE("out of memory");
577 return NO_MEMORY;
578 }
579 memset(pp_buffer, 0, sizeof(*pp_buffer));
580 pp_buffer->input = input;
581 pp_buffer->output = output;
582 pp_buffer->frameNumber = frameNumber;
583 m_inputPPQ.enqueue((void *)pp_buffer);
584 if (!(m_inputMetaQ.isEmpty())) {
585 LOGD("meta queue is not empty, do next job");
586 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
587 } else
588 LOGD("metadata queue is empty");
589 pthread_mutex_unlock(&mReprocJobLock);
590
591 return NO_ERROR;
592 }
593
594 /*===========================================================================
595 * FUNCTION : needsReprocess
596 *
597 * DESCRIPTION: Determine if reprocess is needed.
598 *
599 * PARAMETERS :
600 * @frame : process frame
601 *
602 * RETURN :
603 * TRUE if frame needs to be reprocessed
604 * FALSE is frame does not need to be reprocessed
605 *
606 *==========================================================================*/
needsReprocess(qcamera_fwk_input_pp_data_t * frame)607 bool QCamera3PostProcessor::needsReprocess(qcamera_fwk_input_pp_data_t *frame)
608 {
609 metadata_buffer_t* meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
610 bool edgeModeOn = FALSE;
611 bool noiseRedModeOn = FALSE;
612 bool reproNotDone = TRUE;
613
614 if (frame->reproc_config.reprocess_type == REPROCESS_TYPE_NONE) {
615 return FALSE;
616 }
617
618 // edge detection
619 IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
620 CAM_INTF_META_EDGE_MODE, meta) {
621 edgeModeOn = (CAM_EDGE_MODE_OFF != edgeMode->edge_mode);
622 }
623
624 // noise reduction
625 IF_META_AVAILABLE(uint32_t, noiseRedMode,
626 CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
627 noiseRedModeOn = (CAM_NOISE_REDUCTION_MODE_OFF != *noiseRedMode);
628 }
629
630 IF_META_AVAILABLE(uint8_t, reprocess_flags,
631 CAM_INTF_META_REPROCESS_FLAGS, meta) {
632 reproNotDone = FALSE;
633 }
634
635 return (edgeModeOn || noiseRedModeOn || reproNotDone);
636 }
637
638 /*===========================================================================
639 * FUNCTION : processData
640 *
641 * DESCRIPTION: enqueue data into dataProc thread
642 *
643 * PARAMETERS :
644 * @frame : process frame
645 *
646 * RETURN : int32_t type of status
647 * NO_ERROR -- success
648 * none-zero failure code
649 *
650 * NOTE : depends on if offline reprocess is needed, received frame will
651 * be sent to either input queue of postprocess or jpeg encoding
652 *==========================================================================*/
processData(qcamera_fwk_input_pp_data_t * frame)653 int32_t QCamera3PostProcessor::processData(qcamera_fwk_input_pp_data_t *frame)
654 {
655 if (needsReprocess(frame)) {
656 ATRACE_INT("Camera:Reprocess", 1);
657 LOGH("scheduling framework reprocess");
658 pthread_mutex_lock(&mReprocJobLock);
659 // enqueu to post proc input queue
660 m_inputFWKPPQ.enqueue((void *)frame);
661 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
662 pthread_mutex_unlock(&mReprocJobLock);
663 } else {
664 jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue();
665
666 if (jpeg_settings == NULL) {
667 LOGE("Cannot find jpeg settings");
668 return BAD_VALUE;
669 }
670
671 LOGH("no need offline reprocess, sending to jpeg encoding");
672 qcamera_hal3_jpeg_data_t *jpeg_job =
673 (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
674 if (jpeg_job == NULL) {
675 LOGE("No memory for jpeg job");
676 return NO_MEMORY;
677 }
678
679 memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
680 jpeg_job->fwk_frame = frame;
681 jpeg_job->jpeg_settings = jpeg_settings;
682 jpeg_job->metadata =
683 (metadata_buffer_t *) frame->metadata_buffer.buffer;
684
685 // enqueu to jpeg input queue
686 m_inputJpegQ.enqueue((void *)jpeg_job);
687 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
688 }
689
690 return NO_ERROR;
691 }
692
693 /*===========================================================================
694 * FUNCTION : processPPMetadata
695 *
696 * DESCRIPTION: enqueue data into dataProc thread
697 *
698 * PARAMETERS :
699 * @frame : process metadata frame received from pic channel
700 *
701 * RETURN : int32_t type of status
702 * NO_ERROR -- success
703 * none-zero failure code
704 *
705 *==========================================================================*/
processPPMetadata(mm_camera_super_buf_t * reproc_meta)706 int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta)
707 {
708 LOGD("E");
709 pthread_mutex_lock(&mReprocJobLock);
710 // enqueue to metadata input queue
711 m_inputMetaQ.enqueue((void *)reproc_meta);
712 if (!(m_inputPPQ.isEmpty())) {
713 LOGD("pp queue is not empty, do next job");
714 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
715 } else {
716 LOGD("pp queue is empty, not calling do next job");
717 }
718 pthread_mutex_unlock(&mReprocJobLock);
719 return NO_ERROR;
720 }
721
722 /*===========================================================================
723 * FUNCTION : processJpegSettingData
724 *
725 * DESCRIPTION: enqueue jpegSetting into dataProc thread
726 *
727 * PARAMETERS :
728 * @jpeg_settings : jpeg settings data received from pic channel
729 *
730 * RETURN : int32_t type of status
731 * NO_ERROR -- success
732 * none-zero failure code
733 *
734 *==========================================================================*/
processJpegSettingData(jpeg_settings_t * jpeg_settings)735 int32_t QCamera3PostProcessor::processJpegSettingData(
736 jpeg_settings_t *jpeg_settings)
737 {
738 if (!jpeg_settings) {
739 LOGE("invalid jpeg settings pointer");
740 return -EINVAL;
741 }
742 return m_jpegSettingsQ.enqueue((void *)jpeg_settings);
743 }
744
745 /*===========================================================================
746 * FUNCTION : processPPData
747 *
748 * DESCRIPTION: process received frame after reprocess.
749 *
750 * PARAMETERS :
751 * @frame : received frame from reprocess channel.
752 *
753 * RETURN : int32_t type of status
754 * NO_ERROR -- success
755 * none-zero failure code
756 *
757 * NOTE : The frame after reprocess need to send to jpeg encoding.
758 *==========================================================================*/
processPPData(mm_camera_super_buf_t * frame)759 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame)
760 {
761 qcamera_hal3_pp_data_t *job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
762 ATRACE_INT("Camera:Reprocess", 0);
763 if (job == NULL || ((NULL == job->src_frame) && (NULL == job->fwk_src_frame))) {
764 LOGE("Cannot find reprocess job");
765 return BAD_VALUE;
766 }
767 if (job->jpeg_settings == NULL) {
768 LOGE("Cannot find jpeg settings");
769 return BAD_VALUE;
770 }
771
772 qcamera_hal3_jpeg_data_t *jpeg_job =
773 (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
774 if (jpeg_job == NULL) {
775 LOGE("No memory for jpeg job");
776 return NO_MEMORY;
777 }
778
779 memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
780 jpeg_job->src_frame = frame;
781 if(frame != job->src_frame)
782 jpeg_job->src_reproc_frame = job->src_frame;
783 if (NULL == job->fwk_src_frame) {
784 jpeg_job->metadata = job->metadata;
785 } else {
786 jpeg_job->metadata =
787 (metadata_buffer_t *) job->fwk_src_frame->metadata_buffer.buffer;
788 jpeg_job->fwk_src_buffer = job->fwk_src_frame;
789 }
790 jpeg_job->src_metadata = job->src_metadata;
791 jpeg_job->jpeg_settings = job->jpeg_settings;
792
793 // free pp job buf
794 free(job);
795
796 // enqueu reprocessed frame to jpeg input queue
797 m_inputJpegQ.enqueue((void *)jpeg_job);
798
799 // wait up data proc thread
800 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
801
802 return NO_ERROR;
803 }
804
805 /*===========================================================================
806 * FUNCTION : dequeuePPJob
807 *
808 * DESCRIPTION: find a postprocessing job from ongoing pp queue by frame number
809 *
810 * PARAMETERS :
811 * @frameNumber : frame number for the pp job
812 *
813 * RETURN : ptr to a pp job struct. NULL if not found.
814 *==========================================================================*/
dequeuePPJob(uint32_t frameNumber)815 qcamera_hal3_pp_data_t *QCamera3PostProcessor::dequeuePPJob(uint32_t frameNumber) {
816 qcamera_hal3_pp_data_t *pp_job = NULL;
817 pp_job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
818
819 if (pp_job == NULL) {
820 LOGE("Fatal: ongoing PP queue is empty");
821 return NULL;
822 }
823 if (pp_job->fwk_src_frame &&
824 (pp_job->fwk_src_frame->frameNumber != frameNumber)) {
825 LOGE("head of pp queue doesn't match requested frame number");
826 }
827 return pp_job;
828 }
829
830 /*===========================================================================
831 * FUNCTION : findJpegJobByJobId
832 *
833 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
834 *
835 * PARAMETERS :
836 * @jobId : job Id of the job
837 *
838 * RETURN : ptr to a jpeg job struct. NULL if not found.
839 *
840 * NOTE : Currently only one job is sending to mm-jpeg-interface for jpeg
841 * encoding. Therefore simply dequeue from the ongoing Jpeg Queue
842 * will serve the purpose to find the jpeg job.
843 *==========================================================================*/
findJpegJobByJobId(uint32_t jobId)844 qcamera_hal3_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId)
845 {
846 qcamera_hal3_jpeg_data_t * job = NULL;
847 if (jobId == 0) {
848 LOGE("not a valid jpeg jobId");
849 return NULL;
850 }
851
852 // currely only one jpeg job ongoing, so simply dequeue the head
853 job = (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
854 return job;
855 }
856
857 /*===========================================================================
858 * FUNCTION : releasePPInputData
859 *
860 * DESCRIPTION: callback function to release post process input data node
861 *
862 * PARAMETERS :
863 * @data : ptr to post process input data
864 * @user_data : user data ptr (QCamera3Reprocessor)
865 *
866 * RETURN : None
867 *==========================================================================*/
releasePPInputData(void * data,void * user_data)868 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data)
869 {
870 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
871 if (NULL != pme) {
872 qcamera_hal3_pp_buffer_t *buf = (qcamera_hal3_pp_buffer_t *)data;
873 if (NULL != buf) {
874 if (buf->input) {
875 pme->releaseSuperBuf(buf->input);
876 free(buf->input);
877 buf->input = NULL;
878 }
879 }
880 }
881 }
882
883 /*===========================================================================
884 * FUNCTION : releaseMetaData
885 *
886 * DESCRIPTION: callback function to release metadata camera buffer
887 *
888 * PARAMETERS :
889 * @data : ptr to post process input data
890 * @user_data : user data ptr (QCamera3Reprocessor)
891 *
892 * RETURN : None
893 *==========================================================================*/
releaseMetadata(void * data,void * user_data)894 void QCamera3PostProcessor::releaseMetadata(void *data, void *user_data)
895 {
896 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
897 if (NULL != pme) {
898 pme->m_parent->metadataBufDone((mm_camera_super_buf_t *)data);
899 }
900 }
901
902 /*===========================================================================
903 * FUNCTION : releaseJpegData
904 *
905 * DESCRIPTION: callback function to release jpeg job node
906 *
907 * PARAMETERS :
908 * @data : ptr to ongoing jpeg job data
909 * @user_data : user data ptr (QCamera3Reprocessor)
910 *
911 * RETURN : None
912 *==========================================================================*/
releaseJpegData(void * data,void * user_data)913 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data)
914 {
915 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
916 if (NULL != pme) {
917 pme->releaseJpegJobData((qcamera_hal3_jpeg_data_t *)data);
918 }
919 }
920
921 /*===========================================================================
922 * FUNCTION : releaseOngoingPPData
923 *
924 * DESCRIPTION: callback function to release ongoing postprocess job node
925 *
926 * PARAMETERS :
927 * @data : ptr to onging postprocess job
928 * @user_data : user data ptr (QCamera3Reprocessor)
929 *
930 * RETURN : None
931 *==========================================================================*/
releaseOngoingPPData(void * data,void * user_data)932 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data)
933 {
934 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
935 if (NULL != pme) {
936 qcamera_hal3_pp_data_t *pp_data = (qcamera_hal3_pp_data_t *)data;
937
938 if (pp_data && pp_data->src_frame)
939 pme->releaseSuperBuf(pp_data->src_frame);
940
941 pme->releasePPJobData(pp_data);
942
943 }
944 }
945
946 /*===========================================================================
947 * FUNCTION : releaseSuperBuf
948 *
949 * DESCRIPTION: function to release a superbuf frame by returning back to kernel
950 *
951 * PARAMETERS :
952 * @super_buf : ptr to the superbuf frame
953 *
954 * RETURN : None
955 *==========================================================================*/
releaseSuperBuf(mm_camera_super_buf_t * super_buf)956 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
957 {
958 if (NULL != super_buf) {
959 if (m_parent != NULL) {
960 m_parent->bufDone(super_buf);
961 }
962 }
963 }
964
965 /*===========================================================================
966 * FUNCTION : releaseOfflineBuffers
967 *
968 * DESCRIPTION: function to release/unmap offline buffers if any
969 *
970 * PARAMETERS :
971 * @allBuffers : flag that asks to release all buffers or only one
972 *
973 * RETURN : int32_t type of status
974 * NO_ERROR -- success
975 * none-zero failure code
976 *==========================================================================*/
releaseOfflineBuffers(bool allBuffers)977 int32_t QCamera3PostProcessor::releaseOfflineBuffers(bool allBuffers)
978 {
979 int32_t rc = NO_ERROR;
980
981 if(NULL != m_pReprocChannel) {
982 rc = m_pReprocChannel->unmapOfflineBuffers(allBuffers);
983 }
984
985 return rc;
986 }
987
988 /*===========================================================================
989 * FUNCTION : releaseJpegJobData
990 *
991 * DESCRIPTION: function to release internal resources in jpeg job struct
992 *
993 * PARAMETERS :
994 * @job : ptr to jpeg job struct
995 *
996 * RETURN : None
997 *
998 * NOTE : original source frame need to be queued back to kernel for
999 * future use. Output buf of jpeg job need to be released since
1000 * it's allocated for each job. Exif object need to be deleted.
1001 *==========================================================================*/
releaseJpegJobData(qcamera_hal3_jpeg_data_t * job)1002 void QCamera3PostProcessor::releaseJpegJobData(qcamera_hal3_jpeg_data_t *job)
1003 {
1004 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PPROC_REL_JPEG_JOB_DATA);
1005 int32_t rc = NO_ERROR;
1006 LOGD("E");
1007 if (NULL != job) {
1008 if (NULL != job->src_reproc_frame) {
1009 free(job->src_reproc_frame);
1010 job->src_reproc_frame = NULL;
1011 }
1012
1013 if (NULL != job->src_frame) {
1014 if (NULL != m_pReprocChannel) {
1015 rc = m_pReprocChannel->bufDone(job->src_frame);
1016 if (NO_ERROR != rc)
1017 LOGE("bufDone error: %d", rc);
1018 }
1019 free(job->src_frame);
1020 job->src_frame = NULL;
1021 }
1022
1023 if (NULL != job->fwk_src_buffer) {
1024 free(job->fwk_src_buffer);
1025 job->fwk_src_buffer = NULL;
1026 } else if (NULL != job->src_metadata) {
1027 m_parent->metadataBufDone(job->src_metadata);
1028 free(job->src_metadata);
1029 job->src_metadata = NULL;
1030 }
1031
1032 if (NULL != job->fwk_frame) {
1033 free(job->fwk_frame);
1034 job->fwk_frame = NULL;
1035 }
1036
1037 if (NULL != job->pJpegExifObj) {
1038 delete job->pJpegExifObj;
1039 job->pJpegExifObj = NULL;
1040 }
1041
1042 if (NULL != job->jpeg_settings) {
1043 free(job->jpeg_settings);
1044 job->jpeg_settings = NULL;
1045 }
1046 }
1047 /* Additional trigger to process any pending jobs in the input queue */
1048 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
1049 LOGD("X");
1050 }
1051
1052 /*===========================================================================
1053 * FUNCTION : releasePPJobData
1054 *
1055 * DESCRIPTION: function to release internal resources in p pjob struct
1056 *
1057 * PARAMETERS :
1058 * @job : ptr to pp job struct
1059 *
1060 * RETURN : None
1061 *
1062 * NOTE : Original source metadata buffer needs to be released and
1063 * queued back to kernel for future use. src_frame, src_metadata,
1064 * and fwk_src_frame structures need to be freed.
1065 *==========================================================================*/
releasePPJobData(qcamera_hal3_pp_data_t * pp_job)1066 void QCamera3PostProcessor::releasePPJobData(qcamera_hal3_pp_data_t *pp_job)
1067 {
1068 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PPROC_REL_PP_JOB_DATA);
1069 LOGD("E");
1070 if (NULL != pp_job) {
1071 if (NULL != pp_job->src_frame) {
1072 free(pp_job->src_frame);
1073 if (NULL != pp_job->src_metadata) {
1074 m_parent->metadataBufDone(pp_job->src_metadata);
1075 free(pp_job->src_metadata);
1076 }
1077 pp_job->src_frame = NULL;
1078 pp_job->metadata = NULL;
1079 }
1080
1081 if (NULL != pp_job->fwk_src_frame) {
1082 free(pp_job->fwk_src_frame);
1083 pp_job->fwk_src_frame = NULL;
1084 }
1085 }
1086
1087 /* Additional trigger to process any pending jobs in the input queue */
1088 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
1089 LOGD("X");
1090 }
1091
1092 /*===========================================================================
1093 * FUNCTION : getColorfmtFromImgFmt
1094 *
1095 * DESCRIPTION: function to return jpeg color format based on its image format
1096 *
1097 * PARAMETERS :
1098 * @img_fmt : image format
1099 *
1100 * RETURN : jpeg color format that can be understandable by omx lib
1101 *==========================================================================*/
getColorfmtFromImgFmt(cam_format_t img_fmt)1102 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
1103 {
1104 switch (img_fmt) {
1105 case CAM_FORMAT_YUV_420_NV21:
1106 case CAM_FORMAT_YUV_420_NV21_VENUS:
1107 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1108 case CAM_FORMAT_YUV_420_NV21_ADRENO:
1109 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1110 case CAM_FORMAT_YUV_420_NV12:
1111 case CAM_FORMAT_YUV_420_NV12_VENUS:
1112 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
1113 case CAM_FORMAT_YUV_420_YV12:
1114 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
1115 case CAM_FORMAT_YUV_422_NV61:
1116 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
1117 case CAM_FORMAT_YUV_422_NV16:
1118 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
1119 default:
1120 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1121 }
1122 }
1123
1124 /*===========================================================================
1125 * FUNCTION : getJpegImgTypeFromImgFmt
1126 *
1127 * DESCRIPTION: function to return jpeg encode image type based on its image format
1128 *
1129 * PARAMETERS :
1130 * @img_fmt : image format
1131 *
1132 * RETURN : return jpeg source image format (YUV or Bitstream)
1133 *==========================================================================*/
getJpegImgTypeFromImgFmt(cam_format_t img_fmt)1134 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
1135 {
1136 switch (img_fmt) {
1137 case CAM_FORMAT_YUV_420_NV21:
1138 case CAM_FORMAT_YUV_420_NV21_ADRENO:
1139 case CAM_FORMAT_YUV_420_NV12:
1140 case CAM_FORMAT_YUV_420_NV12_VENUS:
1141 case CAM_FORMAT_YUV_420_NV21_VENUS:
1142 case CAM_FORMAT_YUV_420_YV12:
1143 case CAM_FORMAT_YUV_422_NV61:
1144 case CAM_FORMAT_YUV_422_NV16:
1145 return MM_JPEG_FMT_YUV;
1146 default:
1147 return MM_JPEG_FMT_YUV;
1148 }
1149 }
1150
1151 /*===========================================================================
1152 * FUNCTION : encodeFWKData
1153 *
1154 * DESCRIPTION: function to prepare encoding job information and send to
1155 * mm-jpeg-interface to do the encoding job
1156 *
1157 * PARAMETERS :
1158 * @jpeg_job_data : ptr to a struct saving job related information
1159 * @needNewSess : flag to indicate if a new jpeg encoding session need
1160 * to be created. After creation, this flag will be toggled
1161 *
1162 * RETURN : int32_t type of status
1163 * NO_ERROR -- success
1164 * none-zero failure code
1165 *==========================================================================*/
encodeFWKData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1166 int32_t QCamera3PostProcessor::encodeFWKData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
1167 uint8_t &needNewSess)
1168 {
1169 LOGD("E");
1170 int32_t ret = NO_ERROR;
1171 mm_jpeg_job_t jpg_job;
1172 uint32_t jobId = 0;
1173 qcamera_fwk_input_pp_data_t *recvd_frame = NULL;
1174 metadata_buffer_t *metadata = NULL;
1175 jpeg_settings_t *jpeg_settings = NULL;
1176 QCamera3HardwareInterface* hal_obj = NULL;
1177 mm_jpeg_debug_exif_params_t *exif_debug_params = NULL;
1178 bool needJpegExifRotation = false;
1179
1180 if (NULL == jpeg_job_data) {
1181 LOGE("Invalid jpeg job");
1182 return BAD_VALUE;
1183 }
1184
1185 recvd_frame = jpeg_job_data->fwk_frame;
1186 if (NULL == recvd_frame) {
1187 LOGE("Invalid input buffer");
1188 return BAD_VALUE;
1189 }
1190
1191 metadata = jpeg_job_data->metadata;
1192 if (NULL == metadata) {
1193 LOGE("Invalid metadata buffer");
1194 return BAD_VALUE;
1195 }
1196
1197 jpeg_settings = jpeg_job_data->jpeg_settings;
1198 if (NULL == jpeg_settings) {
1199 LOGE("Invalid jpeg settings buffer");
1200 return BAD_VALUE;
1201 }
1202
1203 if ((NULL != jpeg_job_data->fwk_frame) && (NULL != jpeg_job_data->src_frame)) {
1204 LOGE("Unsupported case both framework and camera source buffers are invalid!");
1205 return BAD_VALUE;
1206 }
1207
1208 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1209 if (hal_obj == NULL) {
1210 LOGE("hal_obj is NULL, Error");
1211 return BAD_VALUE;
1212 }
1213
1214 if (mJpegClientHandle <= 0) {
1215 LOGE("Error: bug here, mJpegClientHandle is 0");
1216 return UNKNOWN_ERROR;
1217 }
1218
1219 cam_dimension_t src_dim;
1220 memset(&src_dim, 0, sizeof(cam_dimension_t));
1221 src_dim.width = recvd_frame->reproc_config.input_stream_dim.width;
1222 src_dim.height = recvd_frame->reproc_config.input_stream_dim.height;
1223
1224 cam_dimension_t dst_dim;
1225 memset(&dst_dim, 0, sizeof(cam_dimension_t));
1226 dst_dim.width = recvd_frame->reproc_config.output_stream_dim.width;
1227 dst_dim.height = recvd_frame->reproc_config.output_stream_dim.height;
1228
1229 cam_rect_t crop;
1230 memset(&crop, 0, sizeof(cam_rect_t));
1231 //TBD_later - Zoom event removed in stream
1232 //main_stream->getCropInfo(crop);
1233
1234 // Set JPEG encode crop in reprocess frame metadata
1235 // If this JPEG crop info exist, encoder should do cropping
1236 IF_META_AVAILABLE(cam_stream_crop_info_t, jpeg_crop,
1237 CAM_INTF_PARM_JPEG_ENCODE_CROP, metadata) {
1238 memcpy(&crop, &(jpeg_crop->crop), sizeof(cam_rect_t));
1239 }
1240
1241 // Set JPEG encode crop in reprocess frame metadata
1242 // If this JPEG scale info exist, encoder should do scaling
1243 IF_META_AVAILABLE(cam_dimension_t, scale_dim,
1244 CAM_INTF_PARM_JPEG_SCALE_DIMENSION, metadata) {
1245 if (scale_dim->width != 0 && scale_dim->height != 0) {
1246 dst_dim.width = scale_dim->width;
1247 dst_dim.height = scale_dim->height;
1248 }
1249 }
1250
1251 needJpegExifRotation = (hal_obj->needJpegExifRotation() || !needsReprocess(recvd_frame));
1252
1253 // If EXIF rotation metadata is added and used to match the JPEG orientation,
1254 // it means CPP rotation is not involved, whether it is because CPP does not
1255 // support rotation, or the reprocessed frame is not sent to CPP.
1256 // Override CAM_INTF_PARM_ROTATION to 0 to avoid wrong CPP rotation info
1257 // to be filled in to JPEG metadata.
1258 if (needJpegExifRotation) {
1259 cam_rotation_info_t rotation_info;
1260 memset(&rotation_info, 0, sizeof(rotation_info));
1261 rotation_info.rotation = ROTATE_0;
1262 rotation_info.streamId = 0;
1263 ADD_SET_PARAM_ENTRY_TO_BATCH(metadata, CAM_INTF_PARM_ROTATION, rotation_info);
1264 }
1265
1266 LOGH("Need new session?:%d", needNewSess);
1267 if (needNewSess) {
1268 //creating a new session, so we must destroy the old one
1269 if ( 0 < mJpegSessionId ) {
1270 ret = mJpegHandle.destroy_session(mJpegSessionId);
1271 if (ret != NO_ERROR) {
1272 LOGE("Error destroying an old jpeg encoding session, id = %d",
1273 mJpegSessionId);
1274 return ret;
1275 }
1276 mJpegSessionId = 0;
1277 }
1278 // create jpeg encoding session
1279 mm_jpeg_encode_params_t encodeParam;
1280 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1281 getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings);
1282 QCamera3StreamMem *memObj = (QCamera3StreamMem *)(recvd_frame->input_buffer.mem_info);
1283 if (NULL == memObj) {
1284 LOGE("Memeory Obj of main frame is NULL");
1285 return NO_MEMORY;
1286 }
1287 // clean and invalidate cache ops through mem obj of the frame
1288 memObj->cleanInvalidateCache(recvd_frame->input_buffer.buf_idx);
1289
1290 LOGH("#src bufs:%d # tmb bufs:%d #dst_bufs:%d",
1291 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1292 if (!needJpegExifRotation &&
1293 (jpeg_settings->jpeg_orientation == 90 ||
1294 jpeg_settings->jpeg_orientation == 270)) {
1295 // swap src width and height, stride and scanline due to rotation
1296 encodeParam.main_dim.src_dim.width = src_dim.height;
1297 encodeParam.main_dim.src_dim.height = src_dim.width;
1298 encodeParam.thumb_dim.src_dim.width = src_dim.height;
1299 encodeParam.thumb_dim.src_dim.height = src_dim.width;
1300
1301 int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride;
1302 encodeParam.src_main_buf[0].offset.mp[0].stride =
1303 encodeParam.src_main_buf[0].offset.mp[0].scanline;
1304 encodeParam.src_main_buf[0].offset.mp[0].scanline = temp;
1305
1306 temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride;
1307 encodeParam.src_thumb_buf[0].offset.mp[0].stride =
1308 encodeParam.src_thumb_buf[0].offset.mp[0].scanline;
1309 encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp;
1310 } else {
1311 encodeParam.main_dim.src_dim = src_dim;
1312 encodeParam.thumb_dim.src_dim = src_dim;
1313 }
1314 encodeParam.main_dim.dst_dim = dst_dim;
1315 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1316
1317 LOGI("Src Buffer cnt = %d, res = %dX%d len = %d rot = %d "
1318 "src_dim = %dX%d dst_dim = %dX%d",
1319 encodeParam.num_src_bufs,
1320 encodeParam.src_main_buf[0].offset.mp[0].stride,
1321 encodeParam.src_main_buf[0].offset.mp[0].scanline,
1322 encodeParam.src_main_buf[0].offset.frame_len,
1323 encodeParam.rotation,
1324 src_dim.width, src_dim.height,
1325 dst_dim.width, dst_dim.height);
1326 LOGI("Src THUMB buf_cnt = %d, res = %dX%d len = %d rot = %d "
1327 "src_dim = %dX%d, dst_dim = %dX%d",
1328 encodeParam.num_tmb_bufs,
1329 encodeParam.src_thumb_buf[0].offset.mp[0].stride,
1330 encodeParam.src_thumb_buf[0].offset.mp[0].scanline,
1331 encodeParam.src_thumb_buf[0].offset.frame_len,
1332 encodeParam.thumb_rotation,
1333 encodeParam.thumb_dim.src_dim.width,
1334 encodeParam.thumb_dim.src_dim.height,
1335 encodeParam.thumb_dim.dst_dim.width,
1336 encodeParam.thumb_dim.dst_dim.height);
1337
1338 LOGH("#src bufs:%d # tmb bufs:%d #dst_bufs:%d",
1339 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1340
1341 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1342 if (ret != NO_ERROR) {
1343 LOGE("Error creating a new jpeg encoding session, ret = %d", ret);
1344 return ret;
1345 }
1346 needNewSess = FALSE;
1347 }
1348
1349 // Fill in new job
1350 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1351 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1352 jpg_job.encode_job.session_id = mJpegSessionId;
1353 jpg_job.encode_job.src_index = 0;
1354 jpg_job.encode_job.dst_index = 0;
1355
1356 // Set main dim job parameters and handle rotation
1357 if (!needJpegExifRotation && (jpeg_settings->jpeg_orientation == 90 ||
1358 jpeg_settings->jpeg_orientation == 270)) {
1359
1360 jpg_job.encode_job.main_dim.src_dim.width = src_dim.height;
1361 jpg_job.encode_job.main_dim.src_dim.height = src_dim.width;
1362
1363 jpg_job.encode_job.main_dim.dst_dim.width = dst_dim.height;
1364 jpg_job.encode_job.main_dim.dst_dim.height = dst_dim.width;
1365
1366 jpg_job.encode_job.main_dim.crop.width = crop.height;
1367 jpg_job.encode_job.main_dim.crop.height = crop.width;
1368 jpg_job.encode_job.main_dim.crop.left = crop.top;
1369 jpg_job.encode_job.main_dim.crop.top = crop.left;
1370 } else {
1371 jpg_job.encode_job.main_dim.src_dim = src_dim;
1372 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1373 jpg_job.encode_job.main_dim.crop = crop;
1374 }
1375
1376 // get 3a sw version info
1377 cam_q3a_version_t sw_version;
1378 memset(&sw_version, 0, sizeof(sw_version));
1379 if (hal_obj)
1380 hal_obj->get3AVersion(sw_version);
1381
1382 // get exif data
1383 QCamera3Exif *pJpegExifObj = getExifData(metadata, jpeg_settings, needJpegExifRotation);
1384 jpeg_job_data->pJpegExifObj = pJpegExifObj;
1385 if (pJpegExifObj != NULL) {
1386 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1387 jpg_job.encode_job.exif_info.numOfEntries =
1388 pJpegExifObj->getNumOfEntries();
1389 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] =
1390 sw_version.major_version;
1391 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] =
1392 sw_version.minor_version;
1393 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] =
1394 sw_version.patch_version;
1395 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] =
1396 sw_version.new_feature_des;
1397 }
1398
1399 // thumbnail dim
1400 LOGH("Thumbnail needed:%d", m_bThumbnailNeeded);
1401 if (m_bThumbnailNeeded == TRUE) {
1402 jpg_job.encode_job.thumb_dim.dst_dim =
1403 jpeg_settings->thumbnail_size;
1404
1405 if (!needJpegExifRotation && (jpeg_settings->jpeg_orientation == 90 ||
1406 jpeg_settings->jpeg_orientation == 270)) {
1407 //swap the thumbnail destination width and height if it has
1408 //already been rotated
1409 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1410 jpg_job.encode_job.thumb_dim.dst_dim.width =
1411 jpg_job.encode_job.thumb_dim.dst_dim.height;
1412 jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1413
1414 jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height;
1415 jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width;
1416
1417 jpg_job.encode_job.thumb_dim.crop.width = crop.height;
1418 jpg_job.encode_job.thumb_dim.crop.height = crop.width;
1419 jpg_job.encode_job.thumb_dim.crop.left = crop.top;
1420 jpg_job.encode_job.thumb_dim.crop.top = crop.left;
1421 } else {
1422 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1423 jpg_job.encode_job.thumb_dim.crop = crop;
1424 }
1425 jpg_job.encode_job.thumb_index = 0;
1426 }
1427
1428 jpg_job.encode_job.cam_exif_params = hal_obj->get3AExifParams();
1429 exif_debug_params = jpg_job.encode_job.cam_exif_params.debug_params;
1430 // Fill in exif debug data
1431 // Allocate for a local copy of debug parameters
1432 jpg_job.encode_job.cam_exif_params.debug_params =
1433 (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t));
1434 if (!jpg_job.encode_job.cam_exif_params.debug_params) {
1435 LOGE("Out of Memory. Allocation failed for 3A debug exif params");
1436 return NO_MEMORY;
1437 }
1438
1439 jpg_job.encode_job.mobicat_mask = hal_obj->getMobicatMask();
1440
1441 if (metadata != NULL) {
1442 // Fill in the metadata passed as parameter
1443 jpg_job.encode_job.p_metadata = metadata;
1444
1445 jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid =
1446 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid;
1447
1448 if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) {
1449 jpg_job.encode_job.p_metadata->mobicat_aec_params =
1450 jpg_job.encode_job.cam_exif_params.cam_3a_params;
1451 }
1452
1453 if (exif_debug_params) {
1454 // Copy debug parameters locally.
1455 memcpy(jpg_job.encode_job.cam_exif_params.debug_params,
1456 exif_debug_params, (sizeof(mm_jpeg_debug_exif_params_t)));
1457 /* Save a copy of 3A debug params */
1458 jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid =
1459 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid;
1460 jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid =
1461 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid;
1462 jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid =
1463 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid;
1464 jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid =
1465 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid;
1466 jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid =
1467 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid;
1468 jpg_job.encode_job.p_metadata->is_statsdebug_bestats_params_valid =
1469 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid;
1470 jpg_job.encode_job.p_metadata->is_statsdebug_bhist_params_valid =
1471 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid;
1472 jpg_job.encode_job.p_metadata->is_statsdebug_3a_tuning_params_valid =
1473 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid;
1474
1475 if (jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid) {
1476 jpg_job.encode_job.p_metadata->statsdebug_ae_data =
1477 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params;
1478 }
1479 if (jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid) {
1480 jpg_job.encode_job.p_metadata->statsdebug_awb_data =
1481 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params;
1482 }
1483 if (jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid) {
1484 jpg_job.encode_job.p_metadata->statsdebug_af_data =
1485 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params;
1486 }
1487 if (jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid) {
1488 jpg_job.encode_job.p_metadata->statsdebug_asd_data =
1489 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params;
1490 }
1491 if (jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid) {
1492 jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data =
1493 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params;
1494 }
1495 if (jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid) {
1496 jpg_job.encode_job.p_metadata->statsdebug_bestats_buffer_data =
1497 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params;
1498 }
1499 if (jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid) {
1500 jpg_job.encode_job.p_metadata->statsdebug_bhist_data =
1501 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params;
1502 }
1503 if (jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid) {
1504 jpg_job.encode_job.p_metadata->statsdebug_3a_tuning_data =
1505 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params;
1506 }
1507 }
1508 } else {
1509 LOGW("Metadata is null");
1510 }
1511
1512 // Multi image info
1513 if (hal_obj->isDeviceLinked() == TRUE) {
1514 jpg_job.encode_job.multi_image_info.type = MM_JPEG_TYPE_JPEG;
1515 jpg_job.encode_job.multi_image_info.num_of_images = 1;
1516 jpg_job.encode_job.multi_image_info.enable_metadata = 1;
1517 if (hal_obj->isMainCamera() == TRUE) {
1518 jpg_job.encode_job.multi_image_info.is_primary = 1;
1519 } else {
1520 jpg_job.encode_job.multi_image_info.is_primary = 0;
1521 }
1522 }
1523
1524 jpg_job.encode_job.hal_version = CAM_HAL_V3;
1525
1526 //Start jpeg encoding
1527 ret = mJpegHandle.start_job(&jpg_job, &jobId);
1528 if (jpg_job.encode_job.cam_exif_params.debug_params) {
1529 free(jpg_job.encode_job.cam_exif_params.debug_params);
1530 }
1531 if (ret == NO_ERROR) {
1532 // remember job info
1533 jpeg_job_data->jobId = jobId;
1534 }
1535
1536 LOGD("X");
1537 return ret;
1538 }
1539
1540 /*===========================================================================
1541 * FUNCTION : encodeData
1542 *
1543 * DESCRIPTION: function to prepare encoding job information and send to
1544 * mm-jpeg-interface to do the encoding job
1545 *
1546 * PARAMETERS :
1547 * @jpeg_job_data : ptr to a struct saving job related information
1548 * @needNewSess : flag to indicate if a new jpeg encoding session need
1549 * to be created. After creation, this flag will be toggled
1550 *
1551 * RETURN : int32_t type of status
1552 * NO_ERROR -- success
1553 * none-zero failure code
1554 *==========================================================================*/
encodeData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1555 int32_t QCamera3PostProcessor::encodeData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
1556 uint8_t &needNewSess)
1557 {
1558 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PPROC_ENCODEDATA);
1559 LOGD("E");
1560 int32_t ret = NO_ERROR;
1561 mm_jpeg_job_t jpg_job;
1562 uint32_t jobId = 0;
1563 QCamera3Stream *main_stream = NULL;
1564 mm_camera_buf_def_t *main_frame = NULL;
1565 QCamera3Channel *srcChannel = NULL;
1566 mm_camera_super_buf_t *recvd_frame = NULL;
1567 metadata_buffer_t *metadata = NULL;
1568 jpeg_settings_t *jpeg_settings = NULL;
1569 QCamera3HardwareInterface* hal_obj = NULL;
1570 mm_jpeg_debug_exif_params_t *exif_debug_params = NULL;
1571 if (m_parent != NULL) {
1572 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1573 if (hal_obj == NULL) {
1574 LOGE("hal_obj is NULL, Error");
1575 return BAD_VALUE;
1576 }
1577 } else {
1578 LOGE("m_parent is NULL, Error");
1579 return BAD_VALUE;
1580 }
1581 bool needJpegExifRotation = false;
1582
1583 recvd_frame = jpeg_job_data->src_frame;
1584 metadata = jpeg_job_data->metadata;
1585 jpeg_settings = jpeg_job_data->jpeg_settings;
1586
1587 LOGD("encoding bufIndex: %u",
1588 jpeg_job_data->src_frame->bufs[0]->buf_idx);
1589
1590 QCamera3Channel *pChannel = NULL;
1591 // first check picture channel
1592 if (m_parent->getMyHandle() == recvd_frame->ch_id) {
1593 pChannel = m_parent;
1594 }
1595 // check reprocess channel if not found
1596 if (pChannel == NULL) {
1597 if (m_pReprocChannel != NULL &&
1598 m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
1599 pChannel = m_pReprocChannel;
1600 }
1601 }
1602
1603 srcChannel = pChannel;
1604
1605 if (srcChannel == NULL) {
1606 LOGE("No corresponding channel (ch_id = %d) exist, return here",
1607 recvd_frame->ch_id);
1608 return BAD_VALUE;
1609 }
1610
1611 // find snapshot frame and thumnail frame
1612 //Note: In this version we will receive only snapshot frame.
1613 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
1614 QCamera3Stream *srcStream =
1615 srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
1616 if (srcStream != NULL) {
1617 switch (srcStream->getMyType()) {
1618 case CAM_STREAM_TYPE_SNAPSHOT:
1619 case CAM_STREAM_TYPE_OFFLINE_PROC:
1620 main_stream = srcStream;
1621 main_frame = recvd_frame->bufs[i];
1622 break;
1623 default:
1624 break;
1625 }
1626 }
1627 }
1628
1629 if(NULL == main_frame){
1630 LOGE("Main frame is NULL");
1631 return BAD_VALUE;
1632 }
1633
1634 QCamera3StreamMem *memObj = (QCamera3StreamMem *)main_frame->mem_info;
1635 if (NULL == memObj) {
1636 LOGE("Memeory Obj of main frame is NULL");
1637 return NO_MEMORY;
1638 }
1639
1640 // clean and invalidate cache ops through mem obj of the frame
1641 memObj->cleanInvalidateCache(main_frame->buf_idx);
1642
1643 if (mJpegClientHandle <= 0) {
1644 LOGE("Error: bug here, mJpegClientHandle is 0");
1645 return UNKNOWN_ERROR;
1646 }
1647 cam_dimension_t src_dim;
1648 memset(&src_dim, 0, sizeof(cam_dimension_t));
1649 main_stream->getFrameDimension(src_dim);
1650
1651 cam_dimension_t dst_dim;
1652 memset(&dst_dim, 0, sizeof(cam_dimension_t));
1653 if (NO_ERROR != m_parent->getStreamSize(dst_dim)) {
1654 LOGE("Failed to get size of the JPEG stream");
1655 return UNKNOWN_ERROR;
1656 }
1657
1658 needJpegExifRotation = hal_obj->needJpegExifRotation();
1659 IF_META_AVAILABLE(cam_rotation_info_t, rotation_info, CAM_INTF_PARM_ROTATION, metadata) {
1660 if (jpeg_settings->jpeg_orientation != 0 && rotation_info->rotation == ROTATE_0) {
1661 needJpegExifRotation = TRUE;
1662 LOGH("Need EXIF JPEG ROTATION");
1663 }
1664 }
1665
1666 // Although in HAL3, legacy flip mode is not advertised
1667 // default value of CAM_INTF_PARM_FLIP is still added here
1668 // for jpge metadata
1669 int32_t flipMode = 0; // no flip
1670 ADD_SET_PARAM_ENTRY_TO_BATCH(metadata, CAM_INTF_PARM_FLIP, flipMode);
1671
1672 LOGH("Need new session?:%d", needNewSess);
1673 if (needNewSess) {
1674 //creating a new session, so we must destroy the old one
1675 if ( 0 < mJpegSessionId ) {
1676 ret = mJpegHandle.destroy_session(mJpegSessionId);
1677 if (ret != NO_ERROR) {
1678 LOGE("Error destroying an old jpeg encoding session, id = %d",
1679 mJpegSessionId);
1680 return ret;
1681 }
1682 mJpegSessionId = 0;
1683 }
1684 // create jpeg encoding session
1685 mm_jpeg_encode_params_t encodeParam;
1686 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1687 getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings);
1688 LOGH("#src bufs:%d # tmb bufs:%d #dst_bufs:%d",
1689 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1690 if (!needJpegExifRotation &&
1691 (jpeg_settings->jpeg_orientation == 90 ||
1692 jpeg_settings->jpeg_orientation == 270)) {
1693 //swap src width and height, stride and scanline due to rotation
1694 encodeParam.main_dim.src_dim.width = src_dim.height;
1695 encodeParam.main_dim.src_dim.height = src_dim.width;
1696 encodeParam.thumb_dim.src_dim.width = src_dim.height;
1697 encodeParam.thumb_dim.src_dim.height = src_dim.width;
1698
1699 int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride;
1700 encodeParam.src_main_buf[0].offset.mp[0].stride =
1701 encodeParam.src_main_buf[0].offset.mp[0].scanline;
1702 encodeParam.src_main_buf[0].offset.mp[0].scanline = temp;
1703
1704 temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride;
1705 encodeParam.src_thumb_buf[0].offset.mp[0].stride =
1706 encodeParam.src_thumb_buf[0].offset.mp[0].scanline;
1707 encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp;
1708 } else {
1709 encodeParam.main_dim.src_dim = src_dim;
1710 encodeParam.thumb_dim.src_dim = src_dim;
1711 }
1712 encodeParam.main_dim.dst_dim = dst_dim;
1713 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1714
1715 LOGI("Src Buffer cnt = %d, res = %dX%d len = %d rot = %d "
1716 "src_dim = %dX%d dst_dim = %dX%d",
1717 encodeParam.num_src_bufs,
1718 encodeParam.src_main_buf[0].offset.mp[0].stride,
1719 encodeParam.src_main_buf[0].offset.mp[0].scanline,
1720 encodeParam.src_main_buf[0].offset.frame_len,
1721 encodeParam.rotation,
1722 src_dim.width, src_dim.height,
1723 dst_dim.width, dst_dim.height);
1724 LOGI("Src THUMB buf_cnt = %d, res = %dX%d len = %d rot = %d "
1725 "src_dim = %dX%d, dst_dim = %dX%d",
1726 encodeParam.num_tmb_bufs,
1727 encodeParam.src_thumb_buf[0].offset.mp[0].stride,
1728 encodeParam.src_thumb_buf[0].offset.mp[0].scanline,
1729 encodeParam.src_thumb_buf[0].offset.frame_len,
1730 encodeParam.thumb_rotation,
1731 encodeParam.thumb_dim.src_dim.width,
1732 encodeParam.thumb_dim.src_dim.height,
1733 encodeParam.thumb_dim.dst_dim.width,
1734 encodeParam.thumb_dim.dst_dim.height);
1735 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1736 if (ret != NO_ERROR) {
1737 LOGE("Error creating a new jpeg encoding session, ret = %d", ret);
1738 return ret;
1739 }
1740 needNewSess = FALSE;
1741 }
1742
1743 // Fill in new job
1744 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1745 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1746 jpg_job.encode_job.session_id = mJpegSessionId;
1747 jpg_job.encode_job.src_index = (int32_t)main_frame->buf_idx;
1748 jpg_job.encode_job.dst_index = 0;
1749
1750 cam_rect_t crop;
1751 memset(&crop, 0, sizeof(cam_rect_t));
1752 //TBD_later - Zoom event removed in stream
1753 //main_stream->getCropInfo(crop);
1754
1755 // Set main dim job parameters and handle rotation
1756 if (!needJpegExifRotation && (jpeg_settings->jpeg_orientation == 90 ||
1757 jpeg_settings->jpeg_orientation == 270)) {
1758
1759 jpg_job.encode_job.main_dim.src_dim.width = src_dim.height;
1760 jpg_job.encode_job.main_dim.src_dim.height = src_dim.width;
1761
1762 jpg_job.encode_job.main_dim.dst_dim.width = dst_dim.height;
1763 jpg_job.encode_job.main_dim.dst_dim.height = dst_dim.width;
1764
1765 jpg_job.encode_job.main_dim.crop.width = crop.height;
1766 jpg_job.encode_job.main_dim.crop.height = crop.width;
1767 jpg_job.encode_job.main_dim.crop.left = crop.top;
1768 jpg_job.encode_job.main_dim.crop.top = crop.left;
1769 } else {
1770 jpg_job.encode_job.main_dim.src_dim = src_dim;
1771 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1772 jpg_job.encode_job.main_dim.crop = crop;
1773 }
1774
1775 // get 3a sw version info
1776 cam_q3a_version_t sw_version;
1777 memset(&sw_version, 0, sizeof(sw_version));
1778
1779 if (hal_obj)
1780 hal_obj->get3AVersion(sw_version);
1781
1782 // get exif data
1783 QCamera3Exif *pJpegExifObj = getExifData(metadata, jpeg_settings, needJpegExifRotation);
1784 jpeg_job_data->pJpegExifObj = pJpegExifObj;
1785 if (pJpegExifObj != NULL) {
1786 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1787 jpg_job.encode_job.exif_info.numOfEntries =
1788 pJpegExifObj->getNumOfEntries();
1789 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] =
1790 sw_version.major_version;
1791 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] =
1792 sw_version.minor_version;
1793 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] =
1794 sw_version.patch_version;
1795 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] =
1796 sw_version.new_feature_des;
1797 }
1798
1799 // thumbnail dim
1800 LOGH("Thumbnail needed:%d", m_bThumbnailNeeded);
1801 if (m_bThumbnailNeeded == TRUE) {
1802 jpg_job.encode_job.thumb_dim.dst_dim =
1803 jpeg_settings->thumbnail_size;
1804
1805 if (!needJpegExifRotation &&
1806 (jpeg_settings->jpeg_orientation == 90 ||
1807 jpeg_settings->jpeg_orientation == 270)) {
1808 //swap the thumbnail destination width and height if it has
1809 //already been rotated
1810 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1811 jpg_job.encode_job.thumb_dim.dst_dim.width =
1812 jpg_job.encode_job.thumb_dim.dst_dim.height;
1813 jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1814
1815 jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height;
1816 jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width;
1817
1818 jpg_job.encode_job.thumb_dim.crop.width = crop.height;
1819 jpg_job.encode_job.thumb_dim.crop.height = crop.width;
1820 jpg_job.encode_job.thumb_dim.crop.left = crop.top;
1821 jpg_job.encode_job.thumb_dim.crop.top = crop.left;
1822 } else {
1823 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1824 jpg_job.encode_job.thumb_dim.crop = crop;
1825 }
1826 jpg_job.encode_job.thumb_index = main_frame->buf_idx;
1827 LOGI("Thumbnail idx = %d src w/h (%dx%d), dst w/h (%dx%d)",
1828 jpg_job.encode_job.thumb_index,
1829 jpg_job.encode_job.thumb_dim.src_dim.width,
1830 jpg_job.encode_job.thumb_dim.src_dim.height,
1831 jpg_job.encode_job.thumb_dim.dst_dim.width,
1832 jpg_job.encode_job.thumb_dim.dst_dim.height);
1833 }
1834 LOGI("Main image idx = %d src w/h (%dx%d), dst w/h (%dx%d)",
1835 jpg_job.encode_job.src_index,
1836 jpg_job.encode_job.main_dim.src_dim.width,
1837 jpg_job.encode_job.main_dim.src_dim.height,
1838 jpg_job.encode_job.main_dim.dst_dim.width,
1839 jpg_job.encode_job.main_dim.dst_dim.height);
1840
1841 jpg_job.encode_job.cam_exif_params = hal_obj->get3AExifParams();
1842 exif_debug_params = jpg_job.encode_job.cam_exif_params.debug_params;
1843
1844 // Allocate for a local copy of debug parameters
1845 jpg_job.encode_job.cam_exif_params.debug_params =
1846 (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t));
1847 if (!jpg_job.encode_job.cam_exif_params.debug_params) {
1848 LOGE("Out of Memory. Allocation failed for 3A debug exif params");
1849 return NO_MEMORY;
1850 }
1851
1852 jpg_job.encode_job.mobicat_mask = hal_obj->getMobicatMask();
1853
1854 if (metadata != NULL) {
1855 //Fill in the metadata passed as parameter
1856 jpg_job.encode_job.p_metadata = metadata;
1857
1858 jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid =
1859 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid;
1860
1861 if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) {
1862 jpg_job.encode_job.p_metadata->mobicat_aec_params =
1863 jpg_job.encode_job.cam_exif_params.cam_3a_params;
1864 }
1865
1866 if (exif_debug_params) {
1867 // Copy debug parameters locally.
1868 memcpy(jpg_job.encode_job.cam_exif_params.debug_params,
1869 exif_debug_params, (sizeof(mm_jpeg_debug_exif_params_t)));
1870 /* Save a copy of 3A debug params */
1871 jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid =
1872 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid;
1873 jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid =
1874 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid;
1875 jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid =
1876 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid;
1877 jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid =
1878 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid;
1879 jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid =
1880 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid;
1881 jpg_job.encode_job.p_metadata->is_statsdebug_bestats_params_valid =
1882 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid;
1883 jpg_job.encode_job.p_metadata->is_statsdebug_bhist_params_valid =
1884 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid;
1885 jpg_job.encode_job.p_metadata->is_statsdebug_3a_tuning_params_valid =
1886 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid;
1887
1888 if (jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid) {
1889 jpg_job.encode_job.p_metadata->statsdebug_ae_data =
1890 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params;
1891 }
1892 if (jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid) {
1893 jpg_job.encode_job.p_metadata->statsdebug_awb_data =
1894 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params;
1895 }
1896 if (jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid) {
1897 jpg_job.encode_job.p_metadata->statsdebug_af_data =
1898 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params;
1899 }
1900 if (jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid) {
1901 jpg_job.encode_job.p_metadata->statsdebug_asd_data =
1902 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params;
1903 }
1904 if (jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid) {
1905 jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data =
1906 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params;
1907 }
1908 if (jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid) {
1909 jpg_job.encode_job.p_metadata->statsdebug_bestats_buffer_data =
1910 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params;
1911 }
1912 if (jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid) {
1913 jpg_job.encode_job.p_metadata->statsdebug_bhist_data =
1914 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params;
1915 }
1916 if (jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid) {
1917 jpg_job.encode_job.p_metadata->statsdebug_3a_tuning_data =
1918 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params;
1919 }
1920 }
1921 } else {
1922 LOGW("Metadata is null");
1923 }
1924
1925 // Multi image info
1926 if (hal_obj->isDeviceLinked() == TRUE) {
1927 jpg_job.encode_job.multi_image_info.type = MM_JPEG_TYPE_JPEG;
1928 jpg_job.encode_job.multi_image_info.num_of_images = 1;
1929 jpg_job.encode_job.multi_image_info.enable_metadata = 1;
1930 if (hal_obj->isMainCamera() == TRUE) {
1931 jpg_job.encode_job.multi_image_info.is_primary = 1;
1932 } else {
1933 jpg_job.encode_job.multi_image_info.is_primary = 0;
1934 }
1935 }
1936
1937 jpg_job.encode_job.hal_version = CAM_HAL_V3;
1938
1939 //Start jpeg encoding
1940 ret = mJpegHandle.start_job(&jpg_job, &jobId);
1941 if (jpg_job.encode_job.cam_exif_params.debug_params) {
1942 free(jpg_job.encode_job.cam_exif_params.debug_params);
1943 }
1944 if (ret == NO_ERROR) {
1945 // remember job info
1946 jpeg_job_data->jobId = jobId;
1947 }
1948
1949 LOGD("X");
1950 return ret;
1951 }
1952
1953 /*===========================================================================
1954 * FUNCTION : dataProcessRoutine
1955 *
1956 * DESCRIPTION: data process routine that handles input data either from input
1957 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do
1958 * reprocess.
1959 *
1960 * PARAMETERS :
1961 * @data : user data ptr (QCamera3PostProcessor)
1962 *
1963 * RETURN : None
1964 *==========================================================================*/
dataProcessRoutine(void * data)1965 void *QCamera3PostProcessor::dataProcessRoutine(void *data)
1966 {
1967 int running = 1;
1968 int ret;
1969 uint8_t is_active = FALSE;
1970 uint8_t needNewSess = TRUE;
1971 mm_camera_super_buf_t *meta_buffer = NULL;
1972 LOGD("E");
1973 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
1974 QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
1975 cmdThread->setName("cam_data_proc");
1976
1977 do {
1978 do {
1979 ret = cam_sem_wait(&cmdThread->cmd_sem);
1980 if (ret != 0 && errno != EINVAL) {
1981 LOGE("cam_sem_wait error (%s)",
1982 strerror(errno));
1983 return NULL;
1984 }
1985 } while (ret != 0);
1986
1987 // we got notified about new cmd avail in cmd queue
1988 camera_cmd_type_t cmd = cmdThread->getCmd();
1989 switch (cmd) {
1990 case CAMERA_CMD_TYPE_START_DATA_PROC:
1991 LOGH("start data proc");
1992 is_active = TRUE;
1993 needNewSess = TRUE;
1994
1995 pme->m_ongoingPPQ.init();
1996 pme->m_inputJpegQ.init();
1997 pme->m_inputPPQ.init();
1998 pme->m_inputFWKPPQ.init();
1999 pme->m_inputMetaQ.init();
2000 cam_sem_post(&cmdThread->sync_sem);
2001
2002 break;
2003 case CAMERA_CMD_TYPE_STOP_DATA_PROC:
2004 {
2005 LOGH("stop data proc");
2006 is_active = FALSE;
2007
2008 // cancel all ongoing jpeg jobs
2009 qcamera_hal3_jpeg_data_t *jpeg_job =
2010 (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
2011 while (jpeg_job != NULL) {
2012 pme->mJpegHandle.abort_job(jpeg_job->jobId);
2013
2014 pme->releaseJpegJobData(jpeg_job);
2015 free(jpeg_job);
2016
2017 jpeg_job = (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
2018 }
2019
2020 // destroy jpeg encoding session
2021 if ( 0 < pme->mJpegSessionId ) {
2022 pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
2023 pme->mJpegSessionId = 0;
2024 }
2025
2026 needNewSess = TRUE;
2027
2028 // flush ongoing postproc Queue
2029 pme->m_ongoingPPQ.flush();
2030
2031 // flush input jpeg Queue
2032 pme->m_inputJpegQ.flush();
2033
2034 // flush input Postproc Queue
2035 pme->m_inputPPQ.flush();
2036
2037 // flush framework input Postproc Queue
2038 pme->m_inputFWKPPQ.flush();
2039
2040 pme->m_inputMetaQ.flush();
2041
2042 // signal cmd is completed
2043 cam_sem_post(&cmdThread->sync_sem);
2044 }
2045 break;
2046 case CAMERA_CMD_TYPE_DO_NEXT_JOB:
2047 {
2048 LOGH("Do next job, active is %d", is_active);
2049 /* needNewSess is set to TRUE as postproc is not re-STARTed
2050 * anymore for every captureRequest */
2051 needNewSess = TRUE;
2052 if (is_active == TRUE) {
2053 // check if there is any ongoing jpeg jobs
2054 if (pme->m_ongoingJpegQ.isEmpty()) {
2055 LOGD("ongoing jpeg queue is empty so doing the jpeg job");
2056 // no ongoing jpeg job, we are fine to send jpeg encoding job
2057 qcamera_hal3_jpeg_data_t *jpeg_job =
2058 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
2059
2060 if (NULL != jpeg_job) {
2061 // add into ongoing jpeg job Q
2062 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
2063
2064 if (jpeg_job->fwk_frame) {
2065 ret = pme->encodeFWKData(jpeg_job, needNewSess);
2066 } else {
2067 ret = pme->encodeData(jpeg_job, needNewSess);
2068 }
2069 if (NO_ERROR != ret) {
2070 // dequeue the last one
2071 pme->m_ongoingJpegQ.dequeue(false);
2072
2073 pme->releaseJpegJobData(jpeg_job);
2074 free(jpeg_job);
2075 }
2076 }
2077 }
2078
2079 // check if there are any framework pp jobs
2080 if (!pme->m_inputFWKPPQ.isEmpty()) {
2081 qcamera_fwk_input_pp_data_t *fwk_frame =
2082 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
2083 if (NULL != fwk_frame) {
2084 qcamera_hal3_pp_data_t *pp_job =
2085 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
2086 jpeg_settings_t *jpeg_settings =
2087 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
2088 if (pp_job != NULL) {
2089 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
2090 pp_job->jpeg_settings = jpeg_settings;
2091 if (pme->m_pReprocChannel != NULL) {
2092 if (NO_ERROR != pme->m_pReprocChannel->overrideFwkMetadata(fwk_frame)) {
2093 LOGE("Failed to extract output crop");
2094 }
2095 // add into ongoing PP job Q
2096 pp_job->fwk_src_frame = fwk_frame;
2097 pme->m_ongoingPPQ.enqueue((void *)pp_job);
2098 ret = pme->m_pReprocChannel->doReprocessOffline(fwk_frame);
2099 if (NO_ERROR != ret) {
2100 // remove from ongoing PP job Q
2101 pme->m_ongoingPPQ.dequeue(false);
2102 }
2103 } else {
2104 LOGE("Reprocess channel is NULL");
2105 ret = -1;
2106 }
2107 } else {
2108 LOGE("no mem for qcamera_hal3_pp_data_t");
2109 ret = -1;
2110 }
2111
2112 if (0 != ret) {
2113 // free pp_job
2114 if (pp_job != NULL) {
2115 free(pp_job);
2116 }
2117 // free frame
2118 if (fwk_frame != NULL) {
2119 free(fwk_frame);
2120 }
2121 }
2122 }
2123 }
2124
2125 LOGH("dequeuing pp frame");
2126 pthread_mutex_lock(&pme->mReprocJobLock);
2127 if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) {
2128 qcamera_hal3_pp_buffer_t *pp_buffer =
2129 (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
2130 meta_buffer =
2131 (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
2132 jpeg_settings_t *jpeg_settings =
2133 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
2134 pthread_mutex_unlock(&pme->mReprocJobLock);
2135 qcamera_hal3_pp_data_t *pp_job =
2136 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
2137 if (pp_job == NULL) {
2138 LOGE("no mem for qcamera_hal3_pp_data_t");
2139 ret = -1;
2140 } else if (meta_buffer == NULL) {
2141 LOGE("failed to dequeue from m_inputMetaQ");
2142 ret = -1;
2143 } else if (pp_buffer == NULL) {
2144 LOGE("failed to dequeue from m_inputPPQ");
2145 ret = -1;
2146 } else if (pp_buffer != NULL){
2147 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
2148 pp_job->src_frame = pp_buffer->input;
2149 pp_job->src_metadata = meta_buffer;
2150 if (meta_buffer->bufs[0] != NULL) {
2151 pp_job->metadata = (metadata_buffer_t *)
2152 meta_buffer->bufs[0]->buffer;
2153 }
2154 pp_job->jpeg_settings = jpeg_settings;
2155 pme->m_ongoingPPQ.enqueue((void *)pp_job);
2156 if (pme->m_pReprocChannel != NULL) {
2157 mm_camera_buf_def_t *meta_buffer_arg = NULL;
2158 meta_buffer_arg = meta_buffer->bufs[0];
2159 qcamera_fwk_input_pp_data_t fwk_frame;
2160 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
2161 fwk_frame.frameNumber = pp_buffer->frameNumber;
2162 ret = pme->m_pReprocChannel->overrideMetadata(
2163 pp_buffer, meta_buffer_arg,
2164 pp_job->jpeg_settings,
2165 fwk_frame);
2166 if (NO_ERROR == ret) {
2167 // add into ongoing PP job Q
2168 ret = pme->m_pReprocChannel->doReprocessOffline(
2169 &fwk_frame, true);
2170 if (NO_ERROR != ret) {
2171 // remove from ongoing PP job Q
2172 pme->m_ongoingPPQ.dequeue(false);
2173 }
2174 }
2175 } else {
2176 LOGE("No reprocess. Calling processPPData directly");
2177 ret = pme->processPPData(pp_buffer->input);
2178 }
2179 }
2180
2181 if (0 != ret) {
2182 // free pp_job
2183 if (pp_job != NULL) {
2184 free(pp_job);
2185 }
2186 // free frame
2187 if (pp_buffer != NULL) {
2188 if (pp_buffer->input) {
2189 pme->releaseSuperBuf(pp_buffer->input);
2190 free(pp_buffer->input);
2191 }
2192 free(pp_buffer);
2193 }
2194 //free metadata
2195 if (NULL != meta_buffer) {
2196 pme->m_parent->metadataBufDone(meta_buffer);
2197 free(meta_buffer);
2198 }
2199 } else {
2200 if (pp_buffer != NULL) {
2201 free(pp_buffer);
2202 }
2203 }
2204 } else {
2205 pthread_mutex_unlock(&pme->mReprocJobLock);
2206 }
2207 } else {
2208 // not active, simply return buf and do no op
2209 qcamera_hal3_jpeg_data_t *jpeg_job =
2210 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
2211 if (NULL != jpeg_job) {
2212 free(jpeg_job);
2213 }
2214
2215 qcamera_hal3_pp_buffer_t* pp_buf =
2216 (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
2217 if (NULL != pp_buf) {
2218 if (pp_buf->input) {
2219 pme->releaseSuperBuf(pp_buf->input);
2220 free(pp_buf->input);
2221 pp_buf->input = NULL;
2222 }
2223 free(pp_buf);
2224 }
2225 mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
2226 if (metadata != NULL) {
2227 pme->m_parent->metadataBufDone(metadata);
2228 free(metadata);
2229 }
2230 qcamera_fwk_input_pp_data_t *fwk_frame =
2231 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
2232 if (NULL != fwk_frame) {
2233 free(fwk_frame);
2234 }
2235 }
2236 }
2237 break;
2238 case CAMERA_CMD_TYPE_EXIT:
2239 running = 0;
2240 break;
2241 default:
2242 break;
2243 }
2244 } while (running);
2245 LOGD("X");
2246 return NULL;
2247 }
2248
2249 /* EXIF related helper methods */
2250
2251 /*===========================================================================
2252 * FUNCTION : getRational
2253 *
2254 * DESCRIPTION: compose rational struct
2255 *
2256 * PARAMETERS :
2257 * @rat : ptr to struct to store rational info
2258 * @num :num of the rational
2259 * @denom : denom of the rational
2260 *
2261 * RETURN : int32_t type of status
2262 * NO_ERROR -- success
2263 * none-zero failure code
2264 *==========================================================================*/
getRational(rat_t * rat,int num,int denom)2265 int32_t getRational(rat_t *rat, int num, int denom)
2266 {
2267 if ((0 > num) || (0 >= denom)) {
2268 LOGE("Negative values");
2269 return BAD_VALUE;
2270 }
2271 if (NULL == rat) {
2272 LOGE("NULL rat input");
2273 return BAD_VALUE;
2274 }
2275 rat->num = (uint32_t)num;
2276 rat->denom = (uint32_t)denom;
2277 return NO_ERROR;
2278 }
2279
2280 /*===========================================================================
2281 * FUNCTION : parseGPSCoordinate
2282 *
2283 * DESCRIPTION: parse GPS coordinate string
2284 *
2285 * PARAMETERS :
2286 * @coord_str : [input] coordinate string
2287 * @coord : [output] ptr to struct to store coordinate
2288 *
2289 * RETURN : int32_t type of status
2290 * NO_ERROR -- success
2291 * none-zero failure code
2292 *==========================================================================*/
parseGPSCoordinate(const char * coord_str,rat_t * coord)2293 int parseGPSCoordinate(const char *coord_str, rat_t* coord)
2294 {
2295 if(coord == NULL) {
2296 LOGE("error, invalid argument coord == NULL");
2297 return BAD_VALUE;
2298 }
2299 double degF = atof(coord_str);
2300 if (degF < 0) {
2301 degF = -degF;
2302 }
2303 double minF = (degF - (int) degF) * 60;
2304 double secF = (minF - (int) minF) * 60;
2305
2306 getRational(&coord[0], (int)degF, 1);
2307 getRational(&coord[1], (int)minF, 1);
2308 getRational(&coord[2], (int)(secF * 10000), 10000);
2309 return NO_ERROR;
2310 }
2311
2312 /*===========================================================================
2313 * FUNCTION : getExifDateTime
2314 *
2315 * DESCRIPTION: query exif date time
2316 *
2317 * PARAMETERS :
2318 * @dateTime : string to store exif date time
2319 * @subsecTime : string to store exif subsec time
2320 *
2321 * RETURN : int32_t type of status
2322 * NO_ERROR -- success
2323 * none-zero failure code
2324 *==========================================================================*/
getExifDateTime(String8 & dateTime,String8 & subsecTime)2325 int32_t getExifDateTime(String8 &dateTime, String8 &subsecTime)
2326 {
2327 int32_t ret = NO_ERROR;
2328
2329 //get time and date from system
2330 struct timeval tv;
2331 struct tm timeinfo_data;
2332
2333 int res = gettimeofday(&tv, NULL);
2334 if (0 == res) {
2335 struct tm *timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2336 if (NULL != timeinfo) {
2337 //Write datetime according to EXIF Spec
2338 //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
2339 dateTime = String8::format("%04d:%02d:%02d %02d:%02d:%02d",
2340 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2341 timeinfo->tm_mday, timeinfo->tm_hour,
2342 timeinfo->tm_min, timeinfo->tm_sec);
2343 //Write subsec according to EXIF Sepc
2344 subsecTime = String8::format("%06ld", tv.tv_usec);
2345 } else {
2346 LOGE("localtime_r() error");
2347 ret = UNKNOWN_ERROR;
2348 }
2349 } else if (-1 == res) {
2350 LOGE("gettimeofday() error: %s", strerror(errno));
2351 ret = UNKNOWN_ERROR;
2352 } else {
2353 LOGE("gettimeofday() unexpected return code: %d", res);
2354 ret = UNKNOWN_ERROR;
2355 }
2356
2357 return ret;
2358 }
2359
2360 /*===========================================================================
2361 * FUNCTION : getExifFocalLength
2362 *
2363 * DESCRIPTION: get exif focal length
2364 *
2365 * PARAMETERS :
2366 * @focalLength : ptr to rational struct to store focal length
2367 * @value : focal length value
2368 *
2369 * RETURN : int32_t type of status
2370 * NO_ERROR -- success
2371 * none-zero failure code
2372 *==========================================================================*/
getExifFocalLength(rat_t * focalLength,float value)2373 int32_t getExifFocalLength(rat_t *focalLength, float value)
2374 {
2375 int focalLengthValue =
2376 (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
2377 return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
2378 }
2379
2380 /*===========================================================================
2381 * FUNCTION : getExifExpTimeInfo
2382 *
2383 * DESCRIPTION: get exif exposure time information
2384 *
2385 * PARAMETERS :
2386 * @expoTimeInfo : rational exposure time value
2387 * @value : exposure time value
2388 * RETURN : nt32_t type of status
2389 * NO_ERROR -- success
2390 * none-zero failure code
2391 *==========================================================================*/
getExifExpTimeInfo(rat_t * expoTimeInfo,int64_t value)2392 int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value)
2393 {
2394
2395 int64_t cal_exposureTime;
2396 if (value != 0)
2397 cal_exposureTime = value;
2398 else
2399 cal_exposureTime = 60;
2400
2401 return getRational(expoTimeInfo, 1, (int)cal_exposureTime);
2402 }
2403
2404 /*===========================================================================
2405 * FUNCTION : getExifGpsProcessingMethod
2406 *
2407 * DESCRIPTION: get GPS processing method
2408 *
2409 * PARAMETERS :
2410 * @gpsProcessingMethod : string to store GPS process method
2411 * @count : length of the string
2412 * @value : the value of the processing method
2413 *
2414 * RETURN : int32_t type of status
2415 * NO_ERROR -- success
2416 * none-zero failure code
2417 *==========================================================================*/
getExifGpsProcessingMethod(char * gpsProcessingMethod,uint32_t & count,char * value)2418 int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
2419 uint32_t &count, char* value)
2420 {
2421 if(value != NULL) {
2422 memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
2423 count = EXIF_ASCII_PREFIX_SIZE;
2424 strlcpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE,
2425 value,
2426 GPS_PROCESSING_METHOD_SIZE);
2427 count += (uint32_t)strlen(value);
2428 gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
2429 return NO_ERROR;
2430 } else {
2431 return BAD_VALUE;
2432 }
2433 }
2434
2435 /*===========================================================================
2436 * FUNCTION : getExifLatitude
2437 *
2438 * DESCRIPTION: get exif latitude
2439 *
2440 * PARAMETERS :
2441 * @latitude : ptr to rational struct to store latitude info
2442 * @latRef : character to indicate latitude reference
2443 * @value : value of the latitude
2444 *
2445 * RETURN : int32_t type of status
2446 * NO_ERROR -- success
2447 * none-zero failure code
2448 *==========================================================================*/
getExifLatitude(rat_t * latitude,char * latRef,double value)2449 int32_t getExifLatitude(rat_t *latitude, char *latRef, double value)
2450 {
2451 char str[30];
2452 snprintf(str, sizeof(str), "%f", value);
2453 if(str[0] != '\0') {
2454 parseGPSCoordinate(str, latitude);
2455
2456 //set Latitude Ref
2457 float latitudeValue = strtof(str, 0);
2458 if(latitudeValue < 0.0f) {
2459 latRef[0] = 'S';
2460 } else {
2461 latRef[0] = 'N';
2462 }
2463 latRef[1] = '\0';
2464 return NO_ERROR;
2465 }else{
2466 return BAD_VALUE;
2467 }
2468 }
2469
2470 /*===========================================================================
2471 * FUNCTION : getExifLongitude
2472 *
2473 * DESCRIPTION: get exif longitude
2474 *
2475 * PARAMETERS :
2476 * @longitude : ptr to rational struct to store longitude info
2477 * @lonRef : character to indicate longitude reference
2478 * @value : value of the longitude
2479 *
2480 * RETURN : int32_t type of status
2481 * NO_ERROR -- success
2482 * none-zero failure code
2483 *==========================================================================*/
getExifLongitude(rat_t * longitude,char * lonRef,double value)2484 int32_t getExifLongitude(rat_t *longitude, char *lonRef, double value)
2485 {
2486 char str[30];
2487 snprintf(str, sizeof(str), "%f", value);
2488 if(str[0] != '\0') {
2489 parseGPSCoordinate(str, longitude);
2490
2491 //set Longitude Ref
2492 float longitudeValue = strtof(str, 0);
2493 if(longitudeValue < 0.0f) {
2494 lonRef[0] = 'W';
2495 } else {
2496 lonRef[0] = 'E';
2497 }
2498 lonRef[1] = '\0';
2499 return NO_ERROR;
2500 }else{
2501 return BAD_VALUE;
2502 }
2503 }
2504
2505 /*===========================================================================
2506 * FUNCTION : getExifAltitude
2507 *
2508 * DESCRIPTION: get exif altitude
2509 *
2510 * PARAMETERS :
2511 * @altitude : ptr to rational struct to store altitude info
2512 * @altRef : character to indicate altitude reference
2513 * @argValue : altitude value
2514 *
2515 * RETURN : int32_t type of status
2516 * NO_ERROR -- success
2517 * none-zero failure code
2518 *==========================================================================*/
getExifAltitude(rat_t * altitude,char * altRef,double argValue)2519 int32_t getExifAltitude(rat_t *altitude, char *altRef, double argValue)
2520 {
2521 char str[30];
2522 snprintf(str, sizeof(str), "%f", argValue);
2523 if (str[0] != '\0') {
2524 double value = atof(str);
2525 *altRef = 0;
2526 if(value < 0){
2527 *altRef = 1;
2528 value = -value;
2529 }
2530 return getRational(altitude, (int)(value * 1000), 1000);
2531 } else {
2532 return BAD_VALUE;
2533 }
2534 }
2535
2536 /*===========================================================================
2537 * FUNCTION : getExifGpsDateTimeStamp
2538 *
2539 * DESCRIPTION: get exif GPS date time stamp
2540 *
2541 * PARAMETERS :
2542 * @gpsDateStamp : GPS date time stamp string
2543 * @bufLen : length of the string
2544 * @gpsTimeStamp : ptr to rational struct to store time stamp info
2545 * @value : timestamp value
2546 *
2547 * RETURN : int32_t type of status
2548 * NO_ERROR -- success
2549 * none-zero failure code
2550 *==========================================================================*/
getExifGpsDateTimeStamp(char * gpsDateStamp,uint32_t bufLen,rat_t * gpsTimeStamp,int64_t value)2551 int32_t getExifGpsDateTimeStamp(char *gpsDateStamp, uint32_t bufLen,
2552 rat_t *gpsTimeStamp, int64_t value)
2553 {
2554 char str[30];
2555 snprintf(str, sizeof(str), "%lld", (long long int)value);
2556 if(str[0] != '\0') {
2557 time_t unixTime = (time_t)atol(str);
2558 struct tm *UTCTimestamp = gmtime(&unixTime);
2559 if (UTCTimestamp != NULL && gpsDateStamp != NULL
2560 && gpsTimeStamp != NULL) {
2561 strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
2562
2563 getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
2564 getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
2565 getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
2566 return NO_ERROR;
2567 } else {
2568 LOGE("Could not get the timestamp");
2569 return BAD_VALUE;
2570 }
2571 } else {
2572 return BAD_VALUE;
2573 }
2574 }
2575
2576 /*===========================================================================
2577 * FUNCTION : getExifExposureValue
2578 *
2579 * DESCRIPTION: get exif GPS date time stamp
2580 *
2581 * PARAMETERS :
2582 * @exposure_val : rational exposure value
2583 * @exposure_comp : exposure compensation
2584 * @step : exposure step
2585 *
2586 * RETURN : int32_t type of status
2587 * NO_ERROR -- success
2588 * none-zero failure code
2589 *==========================================================================*/
getExifExposureValue(srat_t * exposure_val,int32_t exposure_comp,cam_rational_type_t step)2590 int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
2591 cam_rational_type_t step)
2592 {
2593 exposure_val->num = exposure_comp * step.numerator;
2594 exposure_val->denom = step.denominator;
2595 return 0;
2596 }
2597
2598 /*===========================================================================
2599 * FUNCTION : getExifData
2600 *
2601 * DESCRIPTION: get exif data to be passed into jpeg encoding
2602 *
2603 * PARAMETERS :
2604 * @metadata : metadata of the encoding request
2605 * @jpeg_settings : jpeg_settings for encoding
2606 * @needJpegExifRotation: check if rotation need to added in EXIF
2607 *
2608 * RETURN : exif data from user setting and GPS
2609 *==========================================================================*/
getExifData(metadata_buffer_t * metadata,jpeg_settings_t * jpeg_settings,bool needJpegExifRotation)2610 QCamera3Exif *QCamera3PostProcessor::getExifData(metadata_buffer_t *metadata,
2611 jpeg_settings_t *jpeg_settings, bool needJpegExifRotation)
2612 {
2613 QCamera3Exif *exif = new QCamera3Exif();
2614 if (exif == NULL) {
2615 LOGE("No memory for QCamera3Exif");
2616 return NULL;
2617 }
2618 QCamera3HardwareInterface* hal_obj = NULL;
2619 if (m_parent != NULL) {
2620 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
2621 } else {
2622 LOGE("m_parent is NULL, Error");
2623 return NULL;
2624 }
2625
2626 int32_t rc = NO_ERROR;
2627 uint32_t count = 0;
2628
2629 // add exif entries
2630 String8 dateTime;
2631 String8 subsecTime;
2632 rc = getExifDateTime(dateTime, subsecTime);
2633 if (rc == NO_ERROR) {
2634 exif->addEntry(EXIFTAGID_DATE_TIME, EXIF_ASCII,
2635 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2636 exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
2637 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2638 exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_DIGITIZED, EXIF_ASCII,
2639 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2640 exif->addEntry(EXIFTAGID_SUBSEC_TIME, EXIF_ASCII,
2641 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2642 exif->addEntry(EXIFTAGID_SUBSEC_TIME_ORIGINAL, EXIF_ASCII,
2643 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2644 exif->addEntry(EXIFTAGID_SUBSEC_TIME_DIGITIZED, EXIF_ASCII,
2645 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2646 } else {
2647 LOGW("getExifDateTime failed");
2648 }
2649
2650
2651 if (metadata != NULL) {
2652 IF_META_AVAILABLE(float, focal_length, CAM_INTF_META_LENS_FOCAL_LENGTH, metadata) {
2653 rat_t focalLength;
2654 rc = getExifFocalLength(&focalLength, *focal_length);
2655 if (rc == NO_ERROR) {
2656 exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
2657 EXIF_RATIONAL,
2658 1,
2659 (void *)&(focalLength));
2660 } else {
2661 LOGW("getExifFocalLength failed");
2662 }
2663 }
2664
2665 IF_META_AVAILABLE(int32_t, isoSpeed, CAM_INTF_META_SENSOR_SENSITIVITY, metadata) {
2666 int16_t fwk_isoSpeed = (int16_t) *isoSpeed;
2667 exif->addEntry(EXIFTAGID_ISO_SPEED_RATING, EXIF_SHORT, 1, (void *) &(fwk_isoSpeed));
2668 }
2669
2670
2671 IF_META_AVAILABLE(int64_t, sensor_exposure_time,
2672 CAM_INTF_META_SENSOR_EXPOSURE_TIME, metadata) {
2673 rat_t sensorExpTime;
2674 rc = getExifExpTimeInfo(&sensorExpTime, *sensor_exposure_time);
2675 if (rc == NO_ERROR){
2676 exif->addEntry(EXIFTAGID_EXPOSURE_TIME,
2677 EXIF_RATIONAL,
2678 1,
2679 (void *)&(sensorExpTime));
2680 } else {
2681 LOGW("getExifExpTimeInfo failed");
2682 }
2683 }
2684
2685 char* jpeg_gps_processing_method = jpeg_settings->gps_processing_method;
2686 if (strlen(jpeg_gps_processing_method) > 0) {
2687 char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE +
2688 GPS_PROCESSING_METHOD_SIZE];
2689 count = 0;
2690 rc = getExifGpsProcessingMethod(gpsProcessingMethod,
2691 count,
2692 jpeg_gps_processing_method);
2693 if(rc == NO_ERROR) {
2694 exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
2695 EXIF_ASCII,
2696 count,
2697 (void *)gpsProcessingMethod);
2698 } else {
2699 LOGW("getExifGpsProcessingMethod failed");
2700 }
2701 }
2702
2703 if (jpeg_settings->gps_coordinates_valid) {
2704
2705 //latitude
2706 rat_t latitude[3];
2707 char latRef[2];
2708 rc = getExifLatitude(latitude, latRef,
2709 jpeg_settings->gps_coordinates[0]);
2710 if(rc == NO_ERROR) {
2711 exif->addEntry(EXIFTAGID_GPS_LATITUDE,
2712 EXIF_RATIONAL,
2713 3,
2714 (void *)latitude);
2715 exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
2716 EXIF_ASCII,
2717 2,
2718 (void *)latRef);
2719 } else {
2720 LOGW("getExifLatitude failed");
2721 }
2722
2723 //longitude
2724 rat_t longitude[3];
2725 char lonRef[2];
2726 rc = getExifLongitude(longitude, lonRef,
2727 jpeg_settings->gps_coordinates[1]);
2728 if(rc == NO_ERROR) {
2729 exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
2730 EXIF_RATIONAL,
2731 3,
2732 (void *)longitude);
2733
2734 exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
2735 EXIF_ASCII,
2736 2,
2737 (void *)lonRef);
2738 } else {
2739 LOGW("getExifLongitude failed");
2740 }
2741
2742 //altitude
2743 rat_t altitude;
2744 char altRef;
2745 rc = getExifAltitude(&altitude, &altRef,
2746 jpeg_settings->gps_coordinates[2]);
2747 if(rc == NO_ERROR) {
2748 exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
2749 EXIF_RATIONAL,
2750 1,
2751 (void *)&(altitude));
2752
2753 exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
2754 EXIF_BYTE,
2755 1,
2756 (void *)&altRef);
2757 } else {
2758 LOGW("getExifAltitude failed");
2759 }
2760 }
2761
2762 if (jpeg_settings->gps_timestamp_valid) {
2763
2764 char gpsDateStamp[20];
2765 rat_t gpsTimeStamp[3];
2766 rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp,
2767 jpeg_settings->gps_timestamp);
2768 if(rc == NO_ERROR) {
2769 exif->addEntry(EXIFTAGID_GPS_DATESTAMP, EXIF_ASCII,
2770 (uint32_t)(strlen(gpsDateStamp) + 1),
2771 (void *)gpsDateStamp);
2772
2773 exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
2774 EXIF_RATIONAL,
2775 3,
2776 (void *)gpsTimeStamp);
2777 } else {
2778 LOGW("getExifGpsDataTimeStamp failed");
2779 }
2780 }
2781
2782 IF_META_AVAILABLE(int32_t, exposure_comp, CAM_INTF_PARM_EXPOSURE_COMPENSATION, metadata) {
2783 IF_META_AVAILABLE(cam_rational_type_t, comp_step, CAM_INTF_PARM_EV_STEP, metadata) {
2784 srat_t exposure_val;
2785 rc = getExifExposureValue(&exposure_val, *exposure_comp, *comp_step);
2786 if(rc == NO_ERROR) {
2787 exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
2788 EXIF_SRATIONAL,
2789 1,
2790 (void *)(&exposure_val));
2791 } else {
2792 LOGW("getExifExposureValue failed ");
2793 }
2794 }
2795 }
2796 } else {
2797 LOGW("no metadata provided ");
2798 }
2799
2800 #ifdef ENABLE_MODEL_INFO_EXIF
2801
2802 char value[PROPERTY_VALUE_MAX];
2803 if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
2804 exif->addEntry(EXIFTAGID_MAKE, EXIF_ASCII,
2805 (uint32_t)(strlen(value) + 1), (void *)value);
2806 } else {
2807 LOGW("getExifMaker failed");
2808 }
2809
2810 if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
2811 exif->addEntry(EXIFTAGID_MODEL, EXIF_ASCII,
2812 (uint32_t)(strlen(value) + 1), (void *)value);
2813 } else {
2814 LOGW("getExifModel failed");
2815 }
2816
2817 if (property_get("ro.build.description", value, "QCAM-AA") > 0) {
2818 exif->addEntry(EXIFTAGID_SOFTWARE, EXIF_ASCII,
2819 (uint32_t)(strlen(value) + 1), (void *)value);
2820 } else {
2821 LOGW("getExifSoftware failed");
2822 }
2823
2824 #endif
2825
2826 if (jpeg_settings->image_desc_valid) {
2827 if (exif->addEntry(EXIFTAGID_IMAGE_DESCRIPTION, EXIF_ASCII,
2828 strlen(jpeg_settings->image_desc)+1,
2829 (void *)jpeg_settings->image_desc)) {
2830 LOGW("Adding IMAGE_DESCRIPTION tag failed");
2831 }
2832 }
2833
2834 if (needJpegExifRotation) {
2835 int16_t orientation;
2836 switch (jpeg_settings->jpeg_orientation) {
2837 case 0:
2838 orientation = 1;
2839 break;
2840 case 90:
2841 orientation = 6;
2842 break;
2843 case 180:
2844 orientation = 3;
2845 break;
2846 case 270:
2847 orientation = 8;
2848 break;
2849 default:
2850 orientation = 1;
2851 break;
2852 }
2853 exif->addEntry(EXIFTAGID_ORIENTATION,
2854 EXIF_SHORT,
2855 1,
2856 (void *)&orientation);
2857 exif->addEntry(EXIFTAGID_TN_ORIENTATION,
2858 EXIF_SHORT,
2859 1,
2860 (void *)&orientation);
2861
2862 }
2863
2864 return exif;
2865 }
2866
2867 /*===========================================================================
2868 * FUNCTION : QCamera3Exif
2869 *
2870 * DESCRIPTION: constructor of QCamera3Exif
2871 *
2872 * PARAMETERS : None
2873 *
2874 * RETURN : None
2875 *==========================================================================*/
QCamera3Exif()2876 QCamera3Exif::QCamera3Exif()
2877 : m_nNumEntries(0)
2878 {
2879 memset(m_Entries, 0, sizeof(m_Entries));
2880 }
2881
2882 /*===========================================================================
2883 * FUNCTION : ~QCamera3Exif
2884 *
2885 * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
2886 *
2887 * PARAMETERS : None
2888 *
2889 * RETURN : None
2890 *==========================================================================*/
~QCamera3Exif()2891 QCamera3Exif::~QCamera3Exif()
2892 {
2893 for (uint32_t i = 0; i < m_nNumEntries; i++) {
2894 switch (m_Entries[i].tag_entry.type) {
2895 case EXIF_BYTE:
2896 {
2897 if (m_Entries[i].tag_entry.count > 1 &&
2898 m_Entries[i].tag_entry.data._bytes != NULL) {
2899 free(m_Entries[i].tag_entry.data._bytes);
2900 m_Entries[i].tag_entry.data._bytes = NULL;
2901 }
2902 }
2903 break;
2904 case EXIF_ASCII:
2905 {
2906 if (m_Entries[i].tag_entry.data._ascii != NULL) {
2907 free(m_Entries[i].tag_entry.data._ascii);
2908 m_Entries[i].tag_entry.data._ascii = NULL;
2909 }
2910 }
2911 break;
2912 case EXIF_SHORT:
2913 {
2914 if (m_Entries[i].tag_entry.count > 1 &&
2915 m_Entries[i].tag_entry.data._shorts != NULL) {
2916 free(m_Entries[i].tag_entry.data._shorts);
2917 m_Entries[i].tag_entry.data._shorts = NULL;
2918 }
2919 }
2920 break;
2921 case EXIF_LONG:
2922 {
2923 if (m_Entries[i].tag_entry.count > 1 &&
2924 m_Entries[i].tag_entry.data._longs != NULL) {
2925 free(m_Entries[i].tag_entry.data._longs);
2926 m_Entries[i].tag_entry.data._longs = NULL;
2927 }
2928 }
2929 break;
2930 case EXIF_RATIONAL:
2931 {
2932 if (m_Entries[i].tag_entry.count > 1 &&
2933 m_Entries[i].tag_entry.data._rats != NULL) {
2934 free(m_Entries[i].tag_entry.data._rats);
2935 m_Entries[i].tag_entry.data._rats = NULL;
2936 }
2937 }
2938 break;
2939 case EXIF_UNDEFINED:
2940 {
2941 if (m_Entries[i].tag_entry.data._undefined != NULL) {
2942 free(m_Entries[i].tag_entry.data._undefined);
2943 m_Entries[i].tag_entry.data._undefined = NULL;
2944 }
2945 }
2946 break;
2947 case EXIF_SLONG:
2948 {
2949 if (m_Entries[i].tag_entry.count > 1 &&
2950 m_Entries[i].tag_entry.data._slongs != NULL) {
2951 free(m_Entries[i].tag_entry.data._slongs);
2952 m_Entries[i].tag_entry.data._slongs = NULL;
2953 }
2954 }
2955 break;
2956 case EXIF_SRATIONAL:
2957 {
2958 if (m_Entries[i].tag_entry.count > 1 &&
2959 m_Entries[i].tag_entry.data._srats != NULL) {
2960 free(m_Entries[i].tag_entry.data._srats);
2961 m_Entries[i].tag_entry.data._srats = NULL;
2962 }
2963 }
2964 break;
2965 default:
2966 LOGW("Error, Unknown type");
2967 break;
2968 }
2969 }
2970 }
2971
2972 /*===========================================================================
2973 * FUNCTION : addEntry
2974 *
2975 * DESCRIPTION: function to add an entry to exif data
2976 *
2977 * PARAMETERS :
2978 * @tagid : exif tag ID
2979 * @type : data type
2980 * @count : number of data in uint of its type
2981 * @data : input data ptr
2982 *
2983 * RETURN : int32_t type of status
2984 * NO_ERROR -- success
2985 * none-zero failure code
2986 *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)2987 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
2988 exif_tag_type_t type,
2989 uint32_t count,
2990 void *data)
2991 {
2992 int32_t rc = NO_ERROR;
2993 if(m_nNumEntries >= MAX_HAL3_EXIF_TABLE_ENTRIES) {
2994 LOGE("Number of entries exceeded limit");
2995 return NO_MEMORY;
2996 }
2997
2998 m_Entries[m_nNumEntries].tag_id = tagid;
2999 m_Entries[m_nNumEntries].tag_entry.type = type;
3000 m_Entries[m_nNumEntries].tag_entry.count = count;
3001 m_Entries[m_nNumEntries].tag_entry.copy = 1;
3002 switch (type) {
3003 case EXIF_BYTE:
3004 {
3005 if (count > 1) {
3006 uint8_t *values = (uint8_t *)malloc(count);
3007 if (values == NULL) {
3008 LOGE("No memory for byte array");
3009 rc = NO_MEMORY;
3010 } else {
3011 memcpy(values, data, count);
3012 m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
3013 }
3014 } else {
3015 m_Entries[m_nNumEntries].tag_entry.data._byte =
3016 *(uint8_t *)data;
3017 }
3018 }
3019 break;
3020 case EXIF_ASCII:
3021 {
3022 char *str = NULL;
3023 str = (char *)malloc(count + 1);
3024 if (str == NULL) {
3025 LOGE("No memory for ascii string");
3026 rc = NO_MEMORY;
3027 } else {
3028 memset(str, 0, count + 1);
3029 memcpy(str, data, count);
3030 m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
3031 }
3032 }
3033 break;
3034 case EXIF_SHORT:
3035 {
3036 uint16_t *exif_data = (uint16_t *)data;
3037 if (count > 1) {
3038 uint16_t *values =
3039 (uint16_t *)malloc(count * sizeof(uint16_t));
3040 if (values == NULL) {
3041 LOGE("No memory for short array");
3042 rc = NO_MEMORY;
3043 } else {
3044 memcpy(values, exif_data, count * sizeof(uint16_t));
3045 m_Entries[m_nNumEntries].tag_entry.data._shorts = values;
3046 }
3047 } else {
3048 m_Entries[m_nNumEntries].tag_entry.data._short =
3049 *(uint16_t *)data;
3050 }
3051 }
3052 break;
3053 case EXIF_LONG:
3054 {
3055 uint32_t *exif_data = (uint32_t *)data;
3056 if (count > 1) {
3057 uint32_t *values =
3058 (uint32_t *)malloc(count * sizeof(uint32_t));
3059 if (values == NULL) {
3060 LOGE("No memory for long array");
3061 rc = NO_MEMORY;
3062 } else {
3063 memcpy(values, exif_data, count * sizeof(uint32_t));
3064 m_Entries[m_nNumEntries].tag_entry.data._longs = values;
3065 }
3066 } else {
3067 m_Entries[m_nNumEntries].tag_entry.data._long =
3068 *(uint32_t *)data;
3069 }
3070 }
3071 break;
3072 case EXIF_RATIONAL:
3073 {
3074 rat_t *exif_data = (rat_t *)data;
3075 if (count > 1) {
3076 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
3077 if (values == NULL) {
3078 LOGE("No memory for rational array");
3079 rc = NO_MEMORY;
3080 } else {
3081 memcpy(values, exif_data, count * sizeof(rat_t));
3082 m_Entries[m_nNumEntries].tag_entry.data._rats = values;
3083 }
3084 } else {
3085 m_Entries[m_nNumEntries].tag_entry.data._rat =
3086 *(rat_t *)data;
3087 }
3088 }
3089 break;
3090 case EXIF_UNDEFINED:
3091 {
3092 uint8_t *values = (uint8_t *)malloc(count);
3093 if (values == NULL) {
3094 LOGE("No memory for undefined array");
3095 rc = NO_MEMORY;
3096 } else {
3097 memcpy(values, data, count);
3098 m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
3099 }
3100 }
3101 break;
3102 case EXIF_SLONG:
3103 {
3104 int32_t *exif_data = (int32_t *)data;
3105 if (count > 1) {
3106 int32_t *values =
3107 (int32_t *)malloc(count * sizeof(int32_t));
3108 if (values == NULL) {
3109 LOGE("No memory for signed long array");
3110 rc = NO_MEMORY;
3111 } else {
3112 memcpy(values, exif_data, count * sizeof(int32_t));
3113 m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
3114 }
3115 } else {
3116 m_Entries[m_nNumEntries].tag_entry.data._slong =
3117 *(int32_t *)data;
3118 }
3119 }
3120 break;
3121 case EXIF_SRATIONAL:
3122 {
3123 srat_t *exif_data = (srat_t *)data;
3124 if (count > 1) {
3125 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
3126 if (values == NULL) {
3127 LOGE("No memory for sign rational array");
3128 rc = NO_MEMORY;
3129 } else {
3130 memcpy(values, exif_data, count * sizeof(srat_t));
3131 m_Entries[m_nNumEntries].tag_entry.data._srats = values;
3132 }
3133 } else {
3134 m_Entries[m_nNumEntries].tag_entry.data._srat =
3135 *(srat_t *)data;
3136 }
3137 }
3138 break;
3139 default:
3140 LOGE("Error, Unknown type");
3141 break;
3142 }
3143
3144 // Increase number of entries
3145 m_nNumEntries++;
3146 return rc;
3147 }
3148
3149 }; // namespace qcamera
3150