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