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