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