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