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