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 getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings); 1443 LOGH("#src bufs:%d # tmb bufs:%d #dst_bufs:%d", 1444 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs); 1445 if (!needJpegExifRotation && 1446 (jpeg_settings->jpeg_orientation == 90 || 1447 jpeg_settings->jpeg_orientation == 270)) { 1448 //swap src width and height, stride and scanline due to rotation 1449 encodeParam.main_dim.src_dim.width = src_dim.height; 1450 encodeParam.main_dim.src_dim.height = src_dim.width; 1451 encodeParam.thumb_dim.src_dim.width = src_dim.height; 1452 encodeParam.thumb_dim.src_dim.height = src_dim.width; 1453 1454 int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride; 1455 encodeParam.src_main_buf[0].offset.mp[0].stride = 1456 encodeParam.src_main_buf[0].offset.mp[0].scanline; 1457 encodeParam.src_main_buf[0].offset.mp[0].scanline = temp; 1458 1459 temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride; 1460 encodeParam.src_thumb_buf[0].offset.mp[0].stride = 1461 encodeParam.src_thumb_buf[0].offset.mp[0].scanline; 1462 encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp; 1463 } else { 1464 encodeParam.main_dim.src_dim = src_dim; 1465 encodeParam.thumb_dim.src_dim = src_dim; 1466 } 1467 encodeParam.main_dim.dst_dim = dst_dim; 1468 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size; 1469 1470 if (needJpegExifRotation) { 1471 encodeParam.thumb_rotation = (uint32_t)jpeg_settings->jpeg_orientation; 1472 } 1473 1474 LOGI("Src Buffer cnt = %d, res = %dX%d len = %d rot = %d " 1475 "src_dim = %dX%d dst_dim = %dX%d", 1476 encodeParam.num_src_bufs, 1477 encodeParam.src_main_buf[0].offset.mp[0].stride, 1478 encodeParam.src_main_buf[0].offset.mp[0].scanline, 1479 encodeParam.src_main_buf[0].offset.frame_len, 1480 encodeParam.rotation, 1481 src_dim.width, src_dim.height, 1482 dst_dim.width, dst_dim.height); 1483 LOGI("Src THUMB buf_cnt = %d, res = %dX%d len = %d rot = %d " 1484 "src_dim = %dX%d, dst_dim = %dX%d", 1485 encodeParam.num_tmb_bufs, 1486 encodeParam.src_thumb_buf[0].offset.mp[0].stride, 1487 encodeParam.src_thumb_buf[0].offset.mp[0].scanline, 1488 encodeParam.src_thumb_buf[0].offset.frame_len, 1489 encodeParam.thumb_rotation, 1490 encodeParam.thumb_dim.src_dim.width, 1491 encodeParam.thumb_dim.src_dim.height, 1492 encodeParam.thumb_dim.dst_dim.width, 1493 encodeParam.thumb_dim.dst_dim.height); 1494 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId); 1495 if (ret != NO_ERROR) { 1496 LOGE("Error creating a new jpeg encoding session, ret = %d", ret); 1497 return ret; 1498 } 1499 needNewSess = FALSE; 1500 } 1501 1502 // Fill in new job 1503 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t)); 1504 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE; 1505 jpg_job.encode_job.session_id = mJpegSessionId; 1506 jpg_job.encode_job.src_index = (int32_t)main_frame->buf_idx; 1507 jpg_job.encode_job.dst_index = 0; 1508 1509 cam_rect_t crop; 1510 memset(&crop, 0, sizeof(cam_rect_t)); 1511 //TBD_later - Zoom event removed in stream 1512 //main_stream->getCropInfo(crop); 1513 1514 // Set main dim job parameters and handle rotation 1515 if (!needJpegExifRotation && (jpeg_settings->jpeg_orientation == 90 || 1516 jpeg_settings->jpeg_orientation == 270)) { 1517 1518 jpg_job.encode_job.main_dim.src_dim.width = src_dim.height; 1519 jpg_job.encode_job.main_dim.src_dim.height = src_dim.width; 1520 1521 jpg_job.encode_job.main_dim.dst_dim.width = dst_dim.height; 1522 jpg_job.encode_job.main_dim.dst_dim.height = dst_dim.width; 1523 1524 jpg_job.encode_job.main_dim.crop.width = crop.height; 1525 jpg_job.encode_job.main_dim.crop.height = crop.width; 1526 jpg_job.encode_job.main_dim.crop.left = crop.top; 1527 jpg_job.encode_job.main_dim.crop.top = crop.left; 1528 } else { 1529 jpg_job.encode_job.main_dim.src_dim = src_dim; 1530 jpg_job.encode_job.main_dim.dst_dim = dst_dim; 1531 jpg_job.encode_job.main_dim.crop = crop; 1532 } 1533 1534 QCamera3HardwareInterface* obj = (QCamera3HardwareInterface*)m_parent->mUserData; 1535 // get 3a sw version info 1536 cam_q3a_version_t sw_version; 1537 memset(&sw_version, 0, sizeof(sw_version)); 1538 1539 if (obj) 1540 obj->get3AVersion(sw_version); 1541 1542 // get exif data 1543 QCamera3Exif *pJpegExifObj = getExifData(metadata, jpeg_settings); 1544 jpeg_job_data->pJpegExifObj = pJpegExifObj; 1545 if (pJpegExifObj != NULL) { 1546 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries(); 1547 jpg_job.encode_job.exif_info.numOfEntries = 1548 pJpegExifObj->getNumOfEntries(); 1549 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] = 1550 sw_version.major_version; 1551 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] = 1552 sw_version.minor_version; 1553 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] = 1554 sw_version.patch_version; 1555 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] = 1556 sw_version.new_feature_des; 1557 } 1558 1559 // thumbnail dim 1560 LOGH("Thumbnail needed:%d", m_bThumbnailNeeded); 1561 if (m_bThumbnailNeeded == TRUE) { 1562 memset(&crop, 0, sizeof(cam_rect_t)); 1563 jpg_job.encode_job.thumb_dim.dst_dim = 1564 jpeg_settings->thumbnail_size; 1565 1566 if (!needJpegExifRotation && 1567 (jpeg_settings->jpeg_orientation == 90 || 1568 jpeg_settings->jpeg_orientation == 270)) { 1569 //swap the thumbnail destination width and height if it has 1570 //already been rotated 1571 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width; 1572 jpg_job.encode_job.thumb_dim.dst_dim.width = 1573 jpg_job.encode_job.thumb_dim.dst_dim.height; 1574 jpg_job.encode_job.thumb_dim.dst_dim.height = temp; 1575 1576 jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height; 1577 jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width; 1578 } else { 1579 jpg_job.encode_job.thumb_dim.src_dim = src_dim; 1580 } 1581 jpg_job.encode_job.thumb_dim.crop = crop; 1582 jpg_job.encode_job.thumb_index = main_frame->buf_idx; 1583 LOGI("Thumbnail idx = %d src w/h (%dx%d), dst w/h (%dx%d)", 1584 jpg_job.encode_job.thumb_index, 1585 jpg_job.encode_job.thumb_dim.src_dim.width, 1586 jpg_job.encode_job.thumb_dim.src_dim.height, 1587 jpg_job.encode_job.thumb_dim.dst_dim.width, 1588 jpg_job.encode_job.thumb_dim.dst_dim.height); 1589 } 1590 LOGI("Main image idx = %d src w/h (%dx%d), dst w/h (%dx%d)", 1591 jpg_job.encode_job.src_index, 1592 jpg_job.encode_job.main_dim.src_dim.width, 1593 jpg_job.encode_job.main_dim.src_dim.height, 1594 jpg_job.encode_job.main_dim.dst_dim.width, 1595 jpg_job.encode_job.main_dim.dst_dim.height); 1596 1597 jpg_job.encode_job.cam_exif_params = hal_obj->get3AExifParams(); 1598 exif_debug_params = jpg_job.encode_job.cam_exif_params.debug_params; 1599 1600 // Allocate for a local copy of debug parameters 1601 jpg_job.encode_job.cam_exif_params.debug_params = 1602 (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t)); 1603 if (!jpg_job.encode_job.cam_exif_params.debug_params) { 1604 LOGE("Out of Memory. Allocation failed for 3A debug exif params"); 1605 return NO_MEMORY; 1606 } 1607 1608 jpg_job.encode_job.mobicat_mask = hal_obj->getMobicatMask(); 1609 1610 if (metadata != NULL) { 1611 //Fill in the metadata passed as parameter 1612 jpg_job.encode_job.p_metadata = metadata; 1613 1614 jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid = 1615 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid; 1616 1617 if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) { 1618 jpg_job.encode_job.p_metadata->mobicat_aec_params = 1619 jpg_job.encode_job.cam_exif_params.cam_3a_params; 1620 } 1621 1622 if (exif_debug_params) { 1623 // Copy debug parameters locally. 1624 memcpy(jpg_job.encode_job.cam_exif_params.debug_params, 1625 exif_debug_params, (sizeof(mm_jpeg_debug_exif_params_t))); 1626 /* Save a copy of 3A debug params */ 1627 jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid = 1628 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid; 1629 jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid = 1630 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid; 1631 jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid = 1632 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid; 1633 jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid = 1634 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid; 1635 jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid = 1636 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid; 1637 jpg_job.encode_job.p_metadata->is_statsdebug_bestats_params_valid = 1638 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid; 1639 jpg_job.encode_job.p_metadata->is_statsdebug_bhist_params_valid = 1640 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid; 1641 jpg_job.encode_job.p_metadata->is_statsdebug_3a_tuning_params_valid = 1642 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid; 1643 1644 if (jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid) { 1645 jpg_job.encode_job.p_metadata->statsdebug_ae_data = 1646 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params; 1647 } 1648 if (jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid) { 1649 jpg_job.encode_job.p_metadata->statsdebug_awb_data = 1650 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params; 1651 } 1652 if (jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid) { 1653 jpg_job.encode_job.p_metadata->statsdebug_af_data = 1654 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params; 1655 } 1656 if (jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid) { 1657 jpg_job.encode_job.p_metadata->statsdebug_asd_data = 1658 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params; 1659 } 1660 if (jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid) { 1661 jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data = 1662 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params; 1663 } 1664 if (jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid) { 1665 jpg_job.encode_job.p_metadata->statsdebug_bestats_buffer_data = 1666 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params; 1667 } 1668 if (jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid) { 1669 jpg_job.encode_job.p_metadata->statsdebug_bhist_data = 1670 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params; 1671 } 1672 if (jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid) { 1673 jpg_job.encode_job.p_metadata->statsdebug_3a_tuning_data = 1674 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params; 1675 } 1676 } 1677 } else { 1678 LOGW("Metadata is null"); 1679 } 1680 1681 jpg_job.encode_job.hal_version = CAM_HAL_V3; 1682 1683 //Start jpeg encoding 1684 ret = mJpegHandle.start_job(&jpg_job, &jobId); 1685 if (jpg_job.encode_job.cam_exif_params.debug_params) { 1686 free(jpg_job.encode_job.cam_exif_params.debug_params); 1687 } 1688 if (ret == NO_ERROR) { 1689 // remember job info 1690 jpeg_job_data->jobId = jobId; 1691 } 1692 1693 LOGD("X"); 1694 return ret; 1695 } 1696 1697 /*=========================================================================== 1698 * FUNCTION : dataProcessRoutine 1699 * 1700 * DESCRIPTION: data process routine that handles input data either from input 1701 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do 1702 * reprocess. 1703 * 1704 * PARAMETERS : 1705 * @data : user data ptr (QCamera3PostProcessor) 1706 * 1707 * RETURN : None 1708 *==========================================================================*/ 1709 void *QCamera3PostProcessor::dataProcessRoutine(void *data) 1710 { 1711 int running = 1; 1712 int ret; 1713 uint8_t is_active = FALSE; 1714 uint8_t needNewSess = TRUE; 1715 mm_camera_super_buf_t *meta_buffer = NULL; 1716 LOGD("E"); 1717 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data; 1718 QCameraCmdThread *cmdThread = &pme->m_dataProcTh; 1719 cmdThread->setName("cam_data_proc"); 1720 1721 do { 1722 do { 1723 ret = cam_sem_wait(&cmdThread->cmd_sem); 1724 if (ret != 0 && errno != EINVAL) { 1725 LOGE("cam_sem_wait error (%s)", 1726 strerror(errno)); 1727 return NULL; 1728 } 1729 } while (ret != 0); 1730 1731 // we got notified about new cmd avail in cmd queue 1732 camera_cmd_type_t cmd = cmdThread->getCmd(); 1733 switch (cmd) { 1734 case CAMERA_CMD_TYPE_START_DATA_PROC: 1735 LOGH("start data proc"); 1736 is_active = TRUE; 1737 needNewSess = TRUE; 1738 1739 pme->m_ongoingPPQ.init(); 1740 pme->m_inputJpegQ.init(); 1741 pme->m_inputPPQ.init(); 1742 pme->m_inputFWKPPQ.init(); 1743 pme->m_inputMetaQ.init(); 1744 cam_sem_post(&cmdThread->sync_sem); 1745 1746 break; 1747 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 1748 { 1749 LOGH("stop data proc"); 1750 is_active = FALSE; 1751 1752 // cancel all ongoing jpeg jobs 1753 qcamera_hal3_jpeg_data_t *jpeg_job = 1754 (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1755 while (jpeg_job != NULL) { 1756 pme->mJpegHandle.abort_job(jpeg_job->jobId); 1757 1758 pme->releaseJpegJobData(jpeg_job); 1759 free(jpeg_job); 1760 1761 jpeg_job = (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1762 } 1763 1764 // destroy jpeg encoding session 1765 if ( 0 < pme->mJpegSessionId ) { 1766 pme->mJpegHandle.destroy_session(pme->mJpegSessionId); 1767 pme->mJpegSessionId = 0; 1768 } 1769 1770 needNewSess = TRUE; 1771 1772 // flush ongoing postproc Queue 1773 pme->m_ongoingPPQ.flush(); 1774 1775 // flush input jpeg Queue 1776 pme->m_inputJpegQ.flush(); 1777 1778 // flush input Postproc Queue 1779 pme->m_inputPPQ.flush(); 1780 1781 // flush framework input Postproc Queue 1782 pme->m_inputFWKPPQ.flush(); 1783 1784 pme->m_inputMetaQ.flush(); 1785 1786 // signal cmd is completed 1787 cam_sem_post(&cmdThread->sync_sem); 1788 } 1789 break; 1790 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 1791 { 1792 LOGH("Do next job, active is %d", is_active); 1793 /* needNewSess is set to TRUE as postproc is not re-STARTed 1794 * anymore for every captureRequest */ 1795 needNewSess = TRUE; 1796 if (is_active == TRUE) { 1797 // check if there is any ongoing jpeg jobs 1798 if (pme->m_ongoingJpegQ.isEmpty()) { 1799 LOGD("ongoing jpeg queue is empty so doing the jpeg job"); 1800 // no ongoing jpeg job, we are fine to send jpeg encoding job 1801 qcamera_hal3_jpeg_data_t *jpeg_job = 1802 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 1803 1804 if (NULL != jpeg_job) { 1805 // add into ongoing jpeg job Q 1806 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job); 1807 1808 if (jpeg_job->fwk_frame) { 1809 ret = pme->encodeFWKData(jpeg_job, needNewSess); 1810 } else { 1811 ret = pme->encodeData(jpeg_job, needNewSess); 1812 } 1813 if (NO_ERROR != ret) { 1814 // dequeue the last one 1815 pme->m_ongoingJpegQ.dequeue(false); 1816 1817 pme->releaseJpegJobData(jpeg_job); 1818 free(jpeg_job); 1819 } 1820 } 1821 } 1822 1823 // check if there are any framework pp jobs 1824 if (!pme->m_inputFWKPPQ.isEmpty()) { 1825 qcamera_fwk_input_pp_data_t *fwk_frame = 1826 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue(); 1827 if (NULL != fwk_frame) { 1828 qcamera_hal3_pp_data_t *pp_job = 1829 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t)); 1830 jpeg_settings_t *jpeg_settings = 1831 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue(); 1832 if (pp_job != NULL) { 1833 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t)); 1834 pp_job->jpeg_settings = jpeg_settings; 1835 if (pme->m_pReprocChannel != NULL) { 1836 if (NO_ERROR != pme->m_pReprocChannel->overrideFwkMetadata(fwk_frame)) { 1837 LOGE("Failed to extract output crop"); 1838 } 1839 // add into ongoing PP job Q 1840 pp_job->fwk_src_frame = fwk_frame; 1841 pme->m_ongoingPPQ.enqueue((void *)pp_job); 1842 ret = pme->m_pReprocChannel->doReprocessOffline(fwk_frame, true); 1843 if (NO_ERROR != ret) { 1844 // remove from ongoing PP job Q 1845 pme->m_ongoingPPQ.dequeue(false); 1846 } 1847 } else { 1848 LOGE("Reprocess channel is NULL"); 1849 ret = -1; 1850 } 1851 } else { 1852 LOGE("no mem for qcamera_hal3_pp_data_t"); 1853 ret = -1; 1854 } 1855 1856 if (0 != ret) { 1857 // free pp_job 1858 if (pp_job != NULL) { 1859 free(pp_job); 1860 } 1861 // free frame 1862 if (fwk_frame != NULL) { 1863 free(fwk_frame); 1864 } 1865 } 1866 } 1867 } 1868 1869 LOGH("dequeuing pp frame"); 1870 pthread_mutex_lock(&pme->mReprocJobLock); 1871 if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) { 1872 qcamera_hal3_pp_buffer_t *pp_buffer = 1873 (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue(); 1874 meta_buffer = 1875 (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue(); 1876 jpeg_settings_t *jpeg_settings = 1877 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue(); 1878 pthread_mutex_unlock(&pme->mReprocJobLock); 1879 qcamera_hal3_pp_data_t *pp_job = 1880 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t)); 1881 if (pp_job == NULL) { 1882 LOGE("no mem for qcamera_hal3_pp_data_t"); 1883 ret = -1; 1884 } else if (meta_buffer == NULL) { 1885 LOGE("failed to dequeue from m_inputMetaQ"); 1886 ret = -1; 1887 } else if (pp_buffer == NULL) { 1888 LOGE("failed to dequeue from m_inputPPQ"); 1889 ret = -1; 1890 } else if (pp_buffer != NULL){ 1891 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t)); 1892 pp_job->src_frame = pp_buffer->input; 1893 pp_job->src_metadata = meta_buffer; 1894 if (meta_buffer->bufs[0] != NULL) { 1895 pp_job->metadata = (metadata_buffer_t *) 1896 meta_buffer->bufs[0]->buffer; 1897 } 1898 pp_job->jpeg_settings = jpeg_settings; 1899 pme->m_ongoingPPQ.enqueue((void *)pp_job); 1900 if (pme->m_pReprocChannel != NULL) { 1901 mm_camera_buf_def_t *meta_buffer_arg = NULL; 1902 meta_buffer_arg = meta_buffer->bufs[0]; 1903 qcamera_fwk_input_pp_data_t fwk_frame; 1904 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t)); 1905 fwk_frame.frameNumber = pp_buffer->frameNumber; 1906 ret = pme->m_pReprocChannel->overrideMetadata( 1907 pp_buffer, meta_buffer_arg, 1908 pp_job->jpeg_settings, 1909 fwk_frame); 1910 if (NO_ERROR == ret) { 1911 // add into ongoing PP job Q 1912 ret = pme->m_pReprocChannel->doReprocessOffline( 1913 &fwk_frame, true); 1914 if (NO_ERROR != ret) { 1915 // remove from ongoing PP job Q 1916 pme->m_ongoingPPQ.dequeue(false); 1917 } 1918 } 1919 } else { 1920 LOGE("No reprocess. Calling processPPData directly"); 1921 ret = pme->processPPData(pp_buffer->input); 1922 } 1923 } 1924 1925 if (0 != ret) { 1926 // free pp_job 1927 if (pp_job != NULL) { 1928 free(pp_job); 1929 } 1930 // free frame 1931 if (pp_buffer != NULL) { 1932 if (pp_buffer->input) { 1933 pme->releaseSuperBuf(pp_buffer->input); 1934 free(pp_buffer->input); 1935 } 1936 free(pp_buffer); 1937 } 1938 //free metadata 1939 if (NULL != meta_buffer) { 1940 pme->m_parent->metadataBufDone(meta_buffer); 1941 free(meta_buffer); 1942 } 1943 } else { 1944 if (pp_buffer != NULL) { 1945 free(pp_buffer); 1946 } 1947 } 1948 } else { 1949 pthread_mutex_unlock(&pme->mReprocJobLock); 1950 } 1951 } else { 1952 // not active, simply return buf and do no op 1953 qcamera_hal3_jpeg_data_t *jpeg_job = 1954 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 1955 if (NULL != jpeg_job) { 1956 free(jpeg_job); 1957 } 1958 1959 qcamera_hal3_pp_buffer_t* pp_buf = 1960 (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue(); 1961 if (NULL != pp_buf) { 1962 if (pp_buf->input) { 1963 pme->releaseSuperBuf(pp_buf->input); 1964 free(pp_buf->input); 1965 pp_buf->input = NULL; 1966 } 1967 free(pp_buf); 1968 } 1969 mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue(); 1970 if (metadata != NULL) { 1971 pme->m_parent->metadataBufDone(metadata); 1972 free(metadata); 1973 } 1974 qcamera_fwk_input_pp_data_t *fwk_frame = 1975 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue(); 1976 if (NULL != fwk_frame) { 1977 free(fwk_frame); 1978 } 1979 } 1980 } 1981 break; 1982 case CAMERA_CMD_TYPE_EXIT: 1983 running = 0; 1984 break; 1985 default: 1986 break; 1987 } 1988 } while (running); 1989 LOGD("X"); 1990 return NULL; 1991 } 1992 1993 /* EXIF related helper methods */ 1994 1995 /*=========================================================================== 1996 * FUNCTION : getRational 1997 * 1998 * DESCRIPTION: compose rational struct 1999 * 2000 * PARAMETERS : 2001 * @rat : ptr to struct to store rational info 2002 * @num :num of the rational 2003 * @denom : denom of the rational 2004 * 2005 * RETURN : int32_t type of status 2006 * NO_ERROR -- success 2007 * none-zero failure code 2008 *==========================================================================*/ 2009 int32_t getRational(rat_t *rat, int num, int denom) 2010 { 2011 if ((0 > num) || (0 >= denom)) { 2012 LOGE("Negative values"); 2013 return BAD_VALUE; 2014 } 2015 if (NULL == rat) { 2016 LOGE("NULL rat input"); 2017 return BAD_VALUE; 2018 } 2019 rat->num = (uint32_t)num; 2020 rat->denom = (uint32_t)denom; 2021 return NO_ERROR; 2022 } 2023 2024 /*=========================================================================== 2025 * FUNCTION : parseGPSCoordinate 2026 * 2027 * DESCRIPTION: parse GPS coordinate string 2028 * 2029 * PARAMETERS : 2030 * @coord_str : [input] coordinate string 2031 * @coord : [output] ptr to struct to store coordinate 2032 * 2033 * RETURN : int32_t type of status 2034 * NO_ERROR -- success 2035 * none-zero failure code 2036 *==========================================================================*/ 2037 int parseGPSCoordinate(const char *coord_str, rat_t* coord) 2038 { 2039 if(coord == NULL) { 2040 LOGE("error, invalid argument coord == NULL"); 2041 return BAD_VALUE; 2042 } 2043 double degF = atof(coord_str); 2044 if (degF < 0) { 2045 degF = -degF; 2046 } 2047 double minF = (degF - (int) degF) * 60; 2048 double secF = (minF - (int) minF) * 60; 2049 2050 getRational(&coord[0], (int)degF, 1); 2051 getRational(&coord[1], (int)minF, 1); 2052 getRational(&coord[2], (int)(secF * 10000), 10000); 2053 return NO_ERROR; 2054 } 2055 2056 /*=========================================================================== 2057 * FUNCTION : getExifDateTime 2058 * 2059 * DESCRIPTION: query exif date time 2060 * 2061 * PARAMETERS : 2062 * @dateTime : string to store exif date time 2063 * @subsecTime : string to store exif subsec time 2064 * 2065 * RETURN : int32_t type of status 2066 * NO_ERROR -- success 2067 * none-zero failure code 2068 *==========================================================================*/ 2069 int32_t getExifDateTime(String8 &dateTime, String8 &subsecTime) 2070 { 2071 int32_t ret = NO_ERROR; 2072 2073 //get time and date from system 2074 struct timeval tv; 2075 struct tm timeinfo_data; 2076 2077 int res = gettimeofday(&tv, NULL); 2078 if (0 == res) { 2079 struct tm *timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data); 2080 if (NULL != timeinfo) { 2081 //Write datetime according to EXIF Spec 2082 //"YYYY:MM:DD HH:MM:SS" (20 chars including \0) 2083 dateTime = String8::format("%04d:%02d:%02d %02d:%02d:%02d", 2084 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, 2085 timeinfo->tm_mday, timeinfo->tm_hour, 2086 timeinfo->tm_min, timeinfo->tm_sec); 2087 //Write subsec according to EXIF Sepc 2088 subsecTime = String8::format("%06ld", tv.tv_usec); 2089 } else { 2090 LOGE("localtime_r() error"); 2091 ret = UNKNOWN_ERROR; 2092 } 2093 } else if (-1 == res) { 2094 LOGE("gettimeofday() error: %s", strerror(errno)); 2095 ret = UNKNOWN_ERROR; 2096 } else { 2097 LOGE("gettimeofday() unexpected return code: %d", res); 2098 ret = UNKNOWN_ERROR; 2099 } 2100 2101 return ret; 2102 } 2103 2104 /*=========================================================================== 2105 * FUNCTION : getExifFocalLength 2106 * 2107 * DESCRIPTION: get exif focal length 2108 * 2109 * PARAMETERS : 2110 * @focalLength : ptr to rational struct to store focal length 2111 * @value : focal length value 2112 * 2113 * RETURN : int32_t type of status 2114 * NO_ERROR -- success 2115 * none-zero failure code 2116 *==========================================================================*/ 2117 int32_t getExifFocalLength(rat_t *focalLength, float value) 2118 { 2119 int focalLengthValue = 2120 (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION); 2121 return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION); 2122 } 2123 2124 /*=========================================================================== 2125 * FUNCTION : getExifExpTimeInfo 2126 * 2127 * DESCRIPTION: get exif exposure time information 2128 * 2129 * PARAMETERS : 2130 * @expoTimeInfo : rational exposure time value 2131 * @value : exposure time value 2132 * RETURN : nt32_t type of status 2133 * NO_ERROR -- success 2134 * none-zero failure code 2135 *==========================================================================*/ 2136 int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value) 2137 { 2138 2139 int64_t cal_exposureTime; 2140 if (value != 0) 2141 cal_exposureTime = value; 2142 else 2143 cal_exposureTime = 60; 2144 2145 return getRational(expoTimeInfo, 1, (int)cal_exposureTime); 2146 } 2147 2148 /*=========================================================================== 2149 * FUNCTION : getExifGpsProcessingMethod 2150 * 2151 * DESCRIPTION: get GPS processing method 2152 * 2153 * PARAMETERS : 2154 * @gpsProcessingMethod : string to store GPS process method 2155 * @count : length of the string 2156 * @value : the value of the processing method 2157 * 2158 * RETURN : int32_t type of status 2159 * NO_ERROR -- success 2160 * none-zero failure code 2161 *==========================================================================*/ 2162 int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod, 2163 uint32_t &count, char* value) 2164 { 2165 if(value != NULL) { 2166 memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE); 2167 count = EXIF_ASCII_PREFIX_SIZE; 2168 strlcpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, 2169 value, 2170 GPS_PROCESSING_METHOD_SIZE); 2171 count += (uint32_t)strlen(value); 2172 gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char 2173 return NO_ERROR; 2174 } else { 2175 return BAD_VALUE; 2176 } 2177 } 2178 2179 /*=========================================================================== 2180 * FUNCTION : getExifLatitude 2181 * 2182 * DESCRIPTION: get exif latitude 2183 * 2184 * PARAMETERS : 2185 * @latitude : ptr to rational struct to store latitude info 2186 * @latRef : character to indicate latitude reference 2187 * @value : value of the latitude 2188 * 2189 * RETURN : int32_t type of status 2190 * NO_ERROR -- success 2191 * none-zero failure code 2192 *==========================================================================*/ 2193 int32_t getExifLatitude(rat_t *latitude, char *latRef, double value) 2194 { 2195 char str[30]; 2196 snprintf(str, sizeof(str), "%f", value); 2197 if(str[0] != '\0') { 2198 parseGPSCoordinate(str, latitude); 2199 2200 //set Latitude Ref 2201 float latitudeValue = strtof(str, 0); 2202 if(latitudeValue < 0.0f) { 2203 latRef[0] = 'S'; 2204 } else { 2205 latRef[0] = 'N'; 2206 } 2207 latRef[1] = '\0'; 2208 return NO_ERROR; 2209 }else{ 2210 return BAD_VALUE; 2211 } 2212 } 2213 2214 /*=========================================================================== 2215 * FUNCTION : getExifLongitude 2216 * 2217 * DESCRIPTION: get exif longitude 2218 * 2219 * PARAMETERS : 2220 * @longitude : ptr to rational struct to store longitude info 2221 * @lonRef : character to indicate longitude reference 2222 * @value : value of the longitude 2223 * 2224 * RETURN : int32_t type of status 2225 * NO_ERROR -- success 2226 * none-zero failure code 2227 *==========================================================================*/ 2228 int32_t getExifLongitude(rat_t *longitude, char *lonRef, double value) 2229 { 2230 char str[30]; 2231 snprintf(str, sizeof(str), "%f", value); 2232 if(str[0] != '\0') { 2233 parseGPSCoordinate(str, longitude); 2234 2235 //set Longitude Ref 2236 float longitudeValue = strtof(str, 0); 2237 if(longitudeValue < 0.0f) { 2238 lonRef[0] = 'W'; 2239 } else { 2240 lonRef[0] = 'E'; 2241 } 2242 lonRef[1] = '\0'; 2243 return NO_ERROR; 2244 }else{ 2245 return BAD_VALUE; 2246 } 2247 } 2248 2249 /*=========================================================================== 2250 * FUNCTION : getExifAltitude 2251 * 2252 * DESCRIPTION: get exif altitude 2253 * 2254 * PARAMETERS : 2255 * @altitude : ptr to rational struct to store altitude info 2256 * @altRef : character to indicate altitude reference 2257 * @argValue : altitude value 2258 * 2259 * RETURN : int32_t type of status 2260 * NO_ERROR -- success 2261 * none-zero failure code 2262 *==========================================================================*/ 2263 int32_t getExifAltitude(rat_t *altitude, char *altRef, double argValue) 2264 { 2265 char str[30]; 2266 snprintf(str, sizeof(str), "%f", argValue); 2267 if (str[0] != '\0') { 2268 double value = atof(str); 2269 *altRef = 0; 2270 if(value < 0){ 2271 *altRef = 1; 2272 value = -value; 2273 } 2274 return getRational(altitude, (int)(value * 1000), 1000); 2275 } else { 2276 return BAD_VALUE; 2277 } 2278 } 2279 2280 /*=========================================================================== 2281 * FUNCTION : getExifGpsDateTimeStamp 2282 * 2283 * DESCRIPTION: get exif GPS date time stamp 2284 * 2285 * PARAMETERS : 2286 * @gpsDateStamp : GPS date time stamp string 2287 * @bufLen : length of the string 2288 * @gpsTimeStamp : ptr to rational struct to store time stamp info 2289 * @value : timestamp value 2290 * 2291 * RETURN : int32_t type of status 2292 * NO_ERROR -- success 2293 * none-zero failure code 2294 *==========================================================================*/ 2295 int32_t getExifGpsDateTimeStamp(char *gpsDateStamp, uint32_t bufLen, 2296 rat_t *gpsTimeStamp, int64_t value) 2297 { 2298 char str[30]; 2299 snprintf(str, sizeof(str), "%lld", (long long int)value); 2300 if(str[0] != '\0') { 2301 time_t unixTime = (time_t)atol(str); 2302 struct tm *UTCTimestamp = gmtime(&unixTime); 2303 if (UTCTimestamp != NULL && gpsDateStamp != NULL 2304 && gpsTimeStamp != NULL) { 2305 strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp); 2306 2307 getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1); 2308 getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1); 2309 getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1); 2310 return NO_ERROR; 2311 } else { 2312 LOGE("Could not get the timestamp"); 2313 return BAD_VALUE; 2314 } 2315 } else { 2316 return BAD_VALUE; 2317 } 2318 } 2319 2320 /*=========================================================================== 2321 * FUNCTION : getExifExposureValue 2322 * 2323 * DESCRIPTION: get exif GPS date time stamp 2324 * 2325 * PARAMETERS : 2326 * @exposure_val : rational exposure value 2327 * @exposure_comp : exposure compensation 2328 * @step : exposure step 2329 * 2330 * RETURN : int32_t type of status 2331 * NO_ERROR -- success 2332 * none-zero failure code 2333 *==========================================================================*/ 2334 int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp, 2335 cam_rational_type_t step) 2336 { 2337 exposure_val->num = exposure_comp * step.numerator; 2338 exposure_val->denom = step.denominator; 2339 return 0; 2340 } 2341 2342 /*=========================================================================== 2343 * FUNCTION : getExifData 2344 * 2345 * DESCRIPTION: get exif data to be passed into jpeg encoding 2346 * 2347 * PARAMETERS : 2348 * @metadata : metadata of the encoding request 2349 * @jpeg_settings : jpeg_settings for encoding 2350 * 2351 * RETURN : exif data from user setting and GPS 2352 *==========================================================================*/ 2353 QCamera3Exif *QCamera3PostProcessor::getExifData(metadata_buffer_t *metadata, 2354 jpeg_settings_t *jpeg_settings) 2355 { 2356 QCamera3Exif *exif = new QCamera3Exif(); 2357 if (exif == NULL) { 2358 LOGE("No memory for QCamera3Exif"); 2359 return NULL; 2360 } 2361 QCamera3HardwareInterface* hal_obj = NULL; 2362 if (m_parent != NULL) { 2363 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData; 2364 } else { 2365 LOGE("m_parent is NULL, Error"); 2366 return NULL; 2367 } 2368 2369 int32_t rc = NO_ERROR; 2370 uint32_t count = 0; 2371 2372 // add exif entries 2373 String8 dateTime; 2374 String8 subsecTime; 2375 rc = getExifDateTime(dateTime, subsecTime); 2376 if (rc == NO_ERROR) { 2377 exif->addEntry(EXIFTAGID_DATE_TIME, EXIF_ASCII, 2378 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string()); 2379 exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII, 2380 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string()); 2381 exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_DIGITIZED, EXIF_ASCII, 2382 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string()); 2383 exif->addEntry(EXIFTAGID_SUBSEC_TIME, EXIF_ASCII, 2384 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string()); 2385 exif->addEntry(EXIFTAGID_SUBSEC_TIME_ORIGINAL, EXIF_ASCII, 2386 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string()); 2387 exif->addEntry(EXIFTAGID_SUBSEC_TIME_DIGITIZED, EXIF_ASCII, 2388 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string()); 2389 } else { 2390 LOGW("getExifDateTime failed"); 2391 } 2392 2393 2394 if (metadata != NULL) { 2395 IF_META_AVAILABLE(float, focal_length, CAM_INTF_META_LENS_FOCAL_LENGTH, metadata) { 2396 rat_t focalLength; 2397 rc = getExifFocalLength(&focalLength, *focal_length); 2398 if (rc == NO_ERROR) { 2399 exif->addEntry(EXIFTAGID_FOCAL_LENGTH, 2400 EXIF_RATIONAL, 2401 1, 2402 (void *)&(focalLength)); 2403 } else { 2404 LOGW("getExifFocalLength failed"); 2405 } 2406 } 2407 2408 IF_META_AVAILABLE(int32_t, isoSpeed, CAM_INTF_META_SENSOR_SENSITIVITY, metadata) { 2409 int16_t fwk_isoSpeed = (int16_t) *isoSpeed; 2410 exif->addEntry(EXIFTAGID_ISO_SPEED_RATING, EXIF_SHORT, 1, (void *) &(fwk_isoSpeed)); 2411 } 2412 2413 2414 IF_META_AVAILABLE(int64_t, sensor_exposure_time, 2415 CAM_INTF_META_SENSOR_EXPOSURE_TIME, metadata) { 2416 rat_t sensorExpTime; 2417 rc = getExifExpTimeInfo(&sensorExpTime, *sensor_exposure_time); 2418 if (rc == NO_ERROR){ 2419 exif->addEntry(EXIFTAGID_EXPOSURE_TIME, 2420 EXIF_RATIONAL, 2421 1, 2422 (void *)&(sensorExpTime)); 2423 } else { 2424 LOGW("getExifExpTimeInfo failed"); 2425 } 2426 } 2427 2428 char* jpeg_gps_processing_method = jpeg_settings->gps_processing_method; 2429 if (strlen(jpeg_gps_processing_method) > 0) { 2430 char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + 2431 GPS_PROCESSING_METHOD_SIZE]; 2432 count = 0; 2433 rc = getExifGpsProcessingMethod(gpsProcessingMethod, 2434 count, 2435 jpeg_gps_processing_method); 2436 if(rc == NO_ERROR) { 2437 exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD, 2438 EXIF_ASCII, 2439 count, 2440 (void *)gpsProcessingMethod); 2441 } else { 2442 LOGW("getExifGpsProcessingMethod failed"); 2443 } 2444 } 2445 2446 if (jpeg_settings->gps_coordinates_valid) { 2447 2448 //latitude 2449 rat_t latitude[3]; 2450 char latRef[2]; 2451 rc = getExifLatitude(latitude, latRef, 2452 jpeg_settings->gps_coordinates[0]); 2453 if(rc == NO_ERROR) { 2454 exif->addEntry(EXIFTAGID_GPS_LATITUDE, 2455 EXIF_RATIONAL, 2456 3, 2457 (void *)latitude); 2458 exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF, 2459 EXIF_ASCII, 2460 2, 2461 (void *)latRef); 2462 } else { 2463 LOGW("getExifLatitude failed"); 2464 } 2465 2466 //longitude 2467 rat_t longitude[3]; 2468 char lonRef[2]; 2469 rc = getExifLongitude(longitude, lonRef, 2470 jpeg_settings->gps_coordinates[1]); 2471 if(rc == NO_ERROR) { 2472 exif->addEntry(EXIFTAGID_GPS_LONGITUDE, 2473 EXIF_RATIONAL, 2474 3, 2475 (void *)longitude); 2476 2477 exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF, 2478 EXIF_ASCII, 2479 2, 2480 (void *)lonRef); 2481 } else { 2482 LOGW("getExifLongitude failed"); 2483 } 2484 2485 //altitude 2486 rat_t altitude; 2487 char altRef; 2488 rc = getExifAltitude(&altitude, &altRef, 2489 jpeg_settings->gps_coordinates[2]); 2490 if(rc == NO_ERROR) { 2491 exif->addEntry(EXIFTAGID_GPS_ALTITUDE, 2492 EXIF_RATIONAL, 2493 1, 2494 (void *)&(altitude)); 2495 2496 exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF, 2497 EXIF_BYTE, 2498 1, 2499 (void *)&altRef); 2500 } else { 2501 LOGW("getExifAltitude failed"); 2502 } 2503 } 2504 2505 if (jpeg_settings->gps_timestamp_valid) { 2506 2507 char gpsDateStamp[20]; 2508 rat_t gpsTimeStamp[3]; 2509 rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, 2510 jpeg_settings->gps_timestamp); 2511 if(rc == NO_ERROR) { 2512 exif->addEntry(EXIFTAGID_GPS_DATESTAMP, EXIF_ASCII, 2513 (uint32_t)(strlen(gpsDateStamp) + 1), 2514 (void *)gpsDateStamp); 2515 2516 exif->addEntry(EXIFTAGID_GPS_TIMESTAMP, 2517 EXIF_RATIONAL, 2518 3, 2519 (void *)gpsTimeStamp); 2520 } else { 2521 LOGW("getExifGpsDataTimeStamp failed"); 2522 } 2523 } 2524 2525 IF_META_AVAILABLE(int32_t, exposure_comp, CAM_INTF_PARM_EXPOSURE_COMPENSATION, metadata) { 2526 IF_META_AVAILABLE(cam_rational_type_t, comp_step, CAM_INTF_PARM_EV_STEP, metadata) { 2527 srat_t exposure_val; 2528 rc = getExifExposureValue(&exposure_val, *exposure_comp, *comp_step); 2529 if(rc == NO_ERROR) { 2530 exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE, 2531 EXIF_SRATIONAL, 2532 1, 2533 (void *)(&exposure_val)); 2534 } else { 2535 LOGW("getExifExposureValue failed "); 2536 } 2537 } 2538 } 2539 } else { 2540 LOGW("no metadata provided "); 2541 } 2542 2543 #ifdef ENABLE_MODEL_INFO_EXIF 2544 2545 char value[PROPERTY_VALUE_MAX]; 2546 if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) { 2547 exif->addEntry(EXIFTAGID_MAKE, EXIF_ASCII, 2548 (uint32_t)(strlen(value) + 1), (void *)value); 2549 } else { 2550 LOGW("getExifMaker failed"); 2551 } 2552 2553 if (property_get("ro.product.model", value, "QCAM-AA") > 0) { 2554 exif->addEntry(EXIFTAGID_MODEL, EXIF_ASCII, 2555 (uint32_t)(strlen(value) + 1), (void *)value); 2556 } else { 2557 LOGW("getExifModel failed"); 2558 } 2559 2560 if (property_get("ro.build.description", value, "QCAM-AA") > 0) { 2561 exif->addEntry(EXIFTAGID_SOFTWARE, EXIF_ASCII, 2562 (uint32_t)(strlen(value) + 1), (void *)value); 2563 } else { 2564 LOGW("getExifSoftware failed"); 2565 } 2566 2567 #endif 2568 2569 if (jpeg_settings->image_desc_valid) { 2570 if (exif->addEntry(EXIFTAGID_IMAGE_DESCRIPTION, EXIF_ASCII, 2571 strlen(jpeg_settings->image_desc)+1, 2572 (void *)jpeg_settings->image_desc)) { 2573 LOGW("Adding IMAGE_DESCRIPTION tag failed"); 2574 } 2575 } 2576 2577 if( hal_obj->needJpegExifRotation()) { 2578 int16_t orientation; 2579 switch (jpeg_settings->jpeg_orientation) { 2580 case 0: 2581 orientation = 1; 2582 break; 2583 case 90: 2584 orientation = 6; 2585 break; 2586 case 180: 2587 orientation = 3; 2588 break; 2589 case 270: 2590 orientation = 8; 2591 break; 2592 default: 2593 orientation = 1; 2594 break; 2595 } 2596 exif->addEntry(EXIFTAGID_ORIENTATION, 2597 EXIF_SHORT, 2598 1, 2599 (void *)&orientation); 2600 exif->addEntry(EXIFTAGID_TN_ORIENTATION, 2601 EXIF_SHORT, 2602 1, 2603 (void *)&orientation); 2604 2605 } 2606 2607 return exif; 2608 } 2609 2610 /*=========================================================================== 2611 * FUNCTION : QCamera3Exif 2612 * 2613 * DESCRIPTION: constructor of QCamera3Exif 2614 * 2615 * PARAMETERS : None 2616 * 2617 * RETURN : None 2618 *==========================================================================*/ 2619 QCamera3Exif::QCamera3Exif() 2620 : m_nNumEntries(0) 2621 { 2622 memset(m_Entries, 0, sizeof(m_Entries)); 2623 } 2624 2625 /*=========================================================================== 2626 * FUNCTION : ~QCamera3Exif 2627 * 2628 * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr. 2629 * 2630 * PARAMETERS : None 2631 * 2632 * RETURN : None 2633 *==========================================================================*/ 2634 QCamera3Exif::~QCamera3Exif() 2635 { 2636 for (uint32_t i = 0; i < m_nNumEntries; i++) { 2637 switch (m_Entries[i].tag_entry.type) { 2638 case EXIF_BYTE: 2639 { 2640 if (m_Entries[i].tag_entry.count > 1 && 2641 m_Entries[i].tag_entry.data._bytes != NULL) { 2642 free(m_Entries[i].tag_entry.data._bytes); 2643 m_Entries[i].tag_entry.data._bytes = NULL; 2644 } 2645 } 2646 break; 2647 case EXIF_ASCII: 2648 { 2649 if (m_Entries[i].tag_entry.data._ascii != NULL) { 2650 free(m_Entries[i].tag_entry.data._ascii); 2651 m_Entries[i].tag_entry.data._ascii = NULL; 2652 } 2653 } 2654 break; 2655 case EXIF_SHORT: 2656 { 2657 if (m_Entries[i].tag_entry.count > 1 && 2658 m_Entries[i].tag_entry.data._shorts != NULL) { 2659 free(m_Entries[i].tag_entry.data._shorts); 2660 m_Entries[i].tag_entry.data._shorts = NULL; 2661 } 2662 } 2663 break; 2664 case EXIF_LONG: 2665 { 2666 if (m_Entries[i].tag_entry.count > 1 && 2667 m_Entries[i].tag_entry.data._longs != NULL) { 2668 free(m_Entries[i].tag_entry.data._longs); 2669 m_Entries[i].tag_entry.data._longs = NULL; 2670 } 2671 } 2672 break; 2673 case EXIF_RATIONAL: 2674 { 2675 if (m_Entries[i].tag_entry.count > 1 && 2676 m_Entries[i].tag_entry.data._rats != NULL) { 2677 free(m_Entries[i].tag_entry.data._rats); 2678 m_Entries[i].tag_entry.data._rats = NULL; 2679 } 2680 } 2681 break; 2682 case EXIF_UNDEFINED: 2683 { 2684 if (m_Entries[i].tag_entry.data._undefined != NULL) { 2685 free(m_Entries[i].tag_entry.data._undefined); 2686 m_Entries[i].tag_entry.data._undefined = NULL; 2687 } 2688 } 2689 break; 2690 case EXIF_SLONG: 2691 { 2692 if (m_Entries[i].tag_entry.count > 1 && 2693 m_Entries[i].tag_entry.data._slongs != NULL) { 2694 free(m_Entries[i].tag_entry.data._slongs); 2695 m_Entries[i].tag_entry.data._slongs = NULL; 2696 } 2697 } 2698 break; 2699 case EXIF_SRATIONAL: 2700 { 2701 if (m_Entries[i].tag_entry.count > 1 && 2702 m_Entries[i].tag_entry.data._srats != NULL) { 2703 free(m_Entries[i].tag_entry.data._srats); 2704 m_Entries[i].tag_entry.data._srats = NULL; 2705 } 2706 } 2707 break; 2708 default: 2709 LOGW("Error, Unknown type"); 2710 break; 2711 } 2712 } 2713 } 2714 2715 /*=========================================================================== 2716 * FUNCTION : addEntry 2717 * 2718 * DESCRIPTION: function to add an entry to exif data 2719 * 2720 * PARAMETERS : 2721 * @tagid : exif tag ID 2722 * @type : data type 2723 * @count : number of data in uint of its type 2724 * @data : input data ptr 2725 * 2726 * RETURN : int32_t type of status 2727 * NO_ERROR -- success 2728 * none-zero failure code 2729 *==========================================================================*/ 2730 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid, 2731 exif_tag_type_t type, 2732 uint32_t count, 2733 void *data) 2734 { 2735 int32_t rc = NO_ERROR; 2736 if(m_nNumEntries >= MAX_HAL3_EXIF_TABLE_ENTRIES) { 2737 LOGE("Number of entries exceeded limit"); 2738 return NO_MEMORY; 2739 } 2740 2741 m_Entries[m_nNumEntries].tag_id = tagid; 2742 m_Entries[m_nNumEntries].tag_entry.type = type; 2743 m_Entries[m_nNumEntries].tag_entry.count = count; 2744 m_Entries[m_nNumEntries].tag_entry.copy = 1; 2745 switch (type) { 2746 case EXIF_BYTE: 2747 { 2748 if (count > 1) { 2749 uint8_t *values = (uint8_t *)malloc(count); 2750 if (values == NULL) { 2751 LOGE("No memory for byte array"); 2752 rc = NO_MEMORY; 2753 } else { 2754 memcpy(values, data, count); 2755 m_Entries[m_nNumEntries].tag_entry.data._bytes = values; 2756 } 2757 } else { 2758 m_Entries[m_nNumEntries].tag_entry.data._byte = 2759 *(uint8_t *)data; 2760 } 2761 } 2762 break; 2763 case EXIF_ASCII: 2764 { 2765 char *str = NULL; 2766 str = (char *)malloc(count + 1); 2767 if (str == NULL) { 2768 LOGE("No memory for ascii string"); 2769 rc = NO_MEMORY; 2770 } else { 2771 memset(str, 0, count + 1); 2772 memcpy(str, data, count); 2773 m_Entries[m_nNumEntries].tag_entry.data._ascii = str; 2774 } 2775 } 2776 break; 2777 case EXIF_SHORT: 2778 { 2779 uint16_t *exif_data = (uint16_t *)data; 2780 if (count > 1) { 2781 uint16_t *values = 2782 (uint16_t *)malloc(count * sizeof(uint16_t)); 2783 if (values == NULL) { 2784 LOGE("No memory for short array"); 2785 rc = NO_MEMORY; 2786 } else { 2787 memcpy(values, exif_data, count * sizeof(uint16_t)); 2788 m_Entries[m_nNumEntries].tag_entry.data._shorts = values; 2789 } 2790 } else { 2791 m_Entries[m_nNumEntries].tag_entry.data._short = 2792 *(uint16_t *)data; 2793 } 2794 } 2795 break; 2796 case EXIF_LONG: 2797 { 2798 uint32_t *exif_data = (uint32_t *)data; 2799 if (count > 1) { 2800 uint32_t *values = 2801 (uint32_t *)malloc(count * sizeof(uint32_t)); 2802 if (values == NULL) { 2803 LOGE("No memory for long array"); 2804 rc = NO_MEMORY; 2805 } else { 2806 memcpy(values, exif_data, count * sizeof(uint32_t)); 2807 m_Entries[m_nNumEntries].tag_entry.data._longs = values; 2808 } 2809 } else { 2810 m_Entries[m_nNumEntries].tag_entry.data._long = 2811 *(uint32_t *)data; 2812 } 2813 } 2814 break; 2815 case EXIF_RATIONAL: 2816 { 2817 rat_t *exif_data = (rat_t *)data; 2818 if (count > 1) { 2819 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t)); 2820 if (values == NULL) { 2821 LOGE("No memory for rational array"); 2822 rc = NO_MEMORY; 2823 } else { 2824 memcpy(values, exif_data, count * sizeof(rat_t)); 2825 m_Entries[m_nNumEntries].tag_entry.data._rats = values; 2826 } 2827 } else { 2828 m_Entries[m_nNumEntries].tag_entry.data._rat = 2829 *(rat_t *)data; 2830 } 2831 } 2832 break; 2833 case EXIF_UNDEFINED: 2834 { 2835 uint8_t *values = (uint8_t *)malloc(count); 2836 if (values == NULL) { 2837 LOGE("No memory for undefined array"); 2838 rc = NO_MEMORY; 2839 } else { 2840 memcpy(values, data, count); 2841 m_Entries[m_nNumEntries].tag_entry.data._undefined = values; 2842 } 2843 } 2844 break; 2845 case EXIF_SLONG: 2846 { 2847 int32_t *exif_data = (int32_t *)data; 2848 if (count > 1) { 2849 int32_t *values = 2850 (int32_t *)malloc(count * sizeof(int32_t)); 2851 if (values == NULL) { 2852 LOGE("No memory for signed long array"); 2853 rc = NO_MEMORY; 2854 } else { 2855 memcpy(values, exif_data, count * sizeof(int32_t)); 2856 m_Entries[m_nNumEntries].tag_entry.data._slongs =values; 2857 } 2858 } else { 2859 m_Entries[m_nNumEntries].tag_entry.data._slong = 2860 *(int32_t *)data; 2861 } 2862 } 2863 break; 2864 case EXIF_SRATIONAL: 2865 { 2866 srat_t *exif_data = (srat_t *)data; 2867 if (count > 1) { 2868 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t)); 2869 if (values == NULL) { 2870 LOGE("No memory for sign rational array"); 2871 rc = NO_MEMORY; 2872 } else { 2873 memcpy(values, exif_data, count * sizeof(srat_t)); 2874 m_Entries[m_nNumEntries].tag_entry.data._srats = values; 2875 } 2876 } else { 2877 m_Entries[m_nNumEntries].tag_entry.data._srat = 2878 *(srat_t *)data; 2879 } 2880 } 2881 break; 2882 default: 2883 LOGE("Error, Unknown type"); 2884 break; 2885 } 2886 2887 // Increase number of entries 2888 m_nNumEntries++; 2889 return rc; 2890 } 2891 2892 }; // namespace qcamera 2893