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