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