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