1 /* Copyright (c) 2012-2014, 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 30 #define LOG_TAG "QCamera3PostProc" 31 //#define LOG_NDEBUG 0 32 33 #include <stdlib.h> 34 #include <utils/Errors.h> 35 36 #include "QCamera3PostProc.h" 37 #include "QCamera3HWI.h" 38 #include "QCamera3Channel.h" 39 #include "QCamera3Stream.h" 40 41 namespace qcamera { 42 43 /*=========================================================================== 44 * FUNCTION : QCamera3PostProcessor 45 * 46 * DESCRIPTION: constructor of QCamera3PostProcessor. 47 * 48 * PARAMETERS : 49 * @cam_ctrl : ptr to HWI object 50 * 51 * RETURN : None 52 *==========================================================================*/ 53 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3PicChannel* ch_ctrl) 54 : m_parent(ch_ctrl), 55 mJpegCB(NULL), 56 mJpegUserData(NULL), 57 mJpegClientHandle(0), 58 mJpegSessionId(0), 59 m_pJpegExifObj(NULL), 60 m_bThumbnailNeeded(TRUE), 61 m_pReprocChannel(NULL), 62 m_inputPPQ(releasePPInputData, this), 63 m_ongoingPPQ(releaseOngoingPPData, this), 64 m_inputJpegQ(releaseJpegData, this), 65 m_ongoingJpegQ(releaseJpegData, this), 66 m_inputRawQ(releasePPInputData, this), 67 m_inputMetaQ(releaseMetaData, this), 68 m_jpegSettingsQ(releaseJpegSetting, this) 69 { 70 memset(&mJpegHandle, 0, sizeof(mJpegHandle)); 71 pthread_mutex_init(&mReprocJobLock, NULL); 72 } 73 74 /*=========================================================================== 75 * FUNCTION : ~QCamera3PostProcessor 76 * 77 * DESCRIPTION: deconstructor of QCamera3PostProcessor. 78 * 79 * PARAMETERS : None 80 * 81 * RETURN : None 82 *==========================================================================*/ 83 QCamera3PostProcessor::~QCamera3PostProcessor() 84 { 85 if (m_pJpegExifObj != NULL) { 86 delete m_pJpegExifObj; 87 m_pJpegExifObj = NULL; 88 } 89 pthread_mutex_destroy(&mReprocJobLock); 90 } 91 92 /*=========================================================================== 93 * FUNCTION : init 94 * 95 * DESCRIPTION: initialization of postprocessor 96 * 97 * PARAMETERS : 98 * @jpeg_cb : callback to handle jpeg event from mm-camera-interface 99 * @user_data : user data ptr for jpeg callback 100 * 101 * RETURN : int32_t type of status 102 * NO_ERROR -- success 103 * none-zero failure code 104 *==========================================================================*/ 105 int32_t QCamera3PostProcessor::init(QCamera3Memory* mMemory, 106 jpeg_encode_callback_t jpeg_cb, void *user_data) 107 { 108 mJpegCB = jpeg_cb; 109 mJpegUserData = user_data; 110 mJpegMem = mMemory; 111 mJpegClientHandle = jpeg_open(&mJpegHandle); 112 if(!mJpegClientHandle) { 113 ALOGE("%s : jpeg_open did not work", __func__); 114 return UNKNOWN_ERROR; 115 } 116 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 m_dataProcTh.exit(); 136 137 if (m_pReprocChannel != NULL) { 138 m_pReprocChannel->stop(); 139 delete m_pReprocChannel; 140 m_pReprocChannel = NULL; 141 } 142 143 if(mJpegClientHandle > 0) { 144 int rc = mJpegHandle.close(mJpegClientHandle); 145 ALOGD("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x", 146 __func__, rc, mJpegClientHandle); 147 mJpegClientHandle = 0; 148 memset(&mJpegHandle, 0, sizeof(mJpegHandle)); 149 } 150 151 mJpegMem = NULL; 152 153 return NO_ERROR; 154 } 155 156 /*=========================================================================== 157 * FUNCTION : start 158 * 159 * DESCRIPTION: start postprocessor. Data process thread and data notify thread 160 * will be launched. 161 * 162 * PARAMETERS : 163 * @pMemory : memory object representing buffers to store JPEG. 164 * @pInputChannel : Input channel obj ptr that possibly needs reprocess 165 * @metadata : metadata for the reprocessing 166 * 167 * RETURN : int32_t type of status 168 * NO_ERROR -- success 169 * none-zero failure code 170 * 171 * NOTE : if any reprocess is needed, a reprocess channel/stream 172 * will be started. 173 *==========================================================================*/ 174 int32_t QCamera3PostProcessor::start(QCamera3Channel *pInputChannel, 175 metadata_buffer_t *metadata) 176 { 177 int32_t rc = NO_ERROR; 178 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData; 179 180 if (hal_obj->needReprocess()) { 181 182 while (!m_inputMetaQ.isEmpty()) { 183 m_pReprocChannel->metadataBufDone((mm_camera_super_buf_t *)m_inputMetaQ.dequeue()); 184 } 185 if (m_pReprocChannel != NULL) { 186 m_pReprocChannel->stop(); 187 delete m_pReprocChannel; 188 m_pReprocChannel = NULL; 189 } 190 191 // if reprocess is needed, start reprocess channel 192 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData; 193 ALOGV("%s: Setting input channel as pInputChannel", __func__); 194 m_pReprocChannel = hal_obj->addOfflineReprocChannel(pInputChannel, m_parent, metadata); 195 if (m_pReprocChannel == NULL) { 196 ALOGE("%s: cannot add reprocess channel", __func__); 197 return UNKNOWN_ERROR; 198 } 199 200 rc = m_pReprocChannel->start(); 201 if (rc != 0) { 202 ALOGE("%s: cannot start reprocess channel", __func__); 203 delete m_pReprocChannel; 204 m_pReprocChannel = NULL; 205 return rc; 206 } 207 } 208 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE); 209 210 return rc; 211 } 212 213 /*=========================================================================== 214 * FUNCTION : stop 215 * 216 * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped. 217 * 218 * PARAMETERS : None 219 * 220 * RETURN : int32_t type of status 221 * NO_ERROR -- success 222 * none-zero failure code 223 * 224 * NOTE : reprocess channel will be stopped and deleted if there is any 225 *==========================================================================*/ 226 int32_t QCamera3PostProcessor::stop() 227 { 228 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE); 229 230 if (m_pReprocChannel != NULL) { 231 m_pReprocChannel->stop(); 232 delete m_pReprocChannel; 233 m_pReprocChannel = NULL; 234 } 235 236 return NO_ERROR; 237 } 238 239 /*=========================================================================== 240 * FUNCTION : getJpegEncodeConfig 241 * 242 * DESCRIPTION: function to prepare encoding job information 243 * 244 * PARAMETERS : 245 * @encode_parm : param to be filled with encoding configuration 246 * #main_stream : stream object where the input buffer comes from 247 * @jpeg_settings : jpeg settings to be applied for encoding 248 * 249 * RETURN : int32_t type of status 250 * NO_ERROR -- success 251 * none-zero failure code 252 *==========================================================================*/ 253 int32_t QCamera3PostProcessor::getJpegEncodeConfig( 254 mm_jpeg_encode_params_t& encode_parm, 255 QCamera3Stream *main_stream, 256 jpeg_settings_t *jpeg_settings) 257 { 258 ALOGV("%s : E", __func__); 259 int32_t ret = NO_ERROR; 260 261 encode_parm.jpeg_cb = mJpegCB; 262 encode_parm.userdata = mJpegUserData; 263 264 if (jpeg_settings->thumbnail_size.width > 0 && 265 jpeg_settings->thumbnail_size.height > 0) 266 m_bThumbnailNeeded = TRUE; 267 else 268 m_bThumbnailNeeded = FALSE; 269 encode_parm.encode_thumbnail = m_bThumbnailNeeded; 270 271 // get color format 272 cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12; //default value 273 main_stream->getFormat(img_fmt); 274 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt); 275 276 // get jpeg quality 277 encode_parm.quality = jpeg_settings->jpeg_quality; 278 279 // get jpeg thumbnail quality 280 encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality; 281 282 cam_frame_len_offset_t main_offset; 283 memset(&main_offset, 0, sizeof(cam_frame_len_offset_t)); 284 main_stream->getFrameOffset(main_offset); 285 286 // src buf config 287 //Pass input main image buffer info to encoder. 288 QCamera3Memory *pStreamMem = main_stream->getStreamBufs(); 289 if (pStreamMem == NULL) { 290 ALOGE("%s: cannot get stream bufs from main stream", __func__); 291 ret = BAD_VALUE; 292 goto on_error; 293 } 294 encode_parm.num_src_bufs = pStreamMem->getCnt(); 295 for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) { 296 if (pStreamMem != NULL) { 297 encode_parm.src_main_buf[i].index = i; 298 encode_parm.src_main_buf[i].buf_size = pStreamMem->getSize(i); 299 encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i); 300 encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i); 301 encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV; 302 encode_parm.src_main_buf[i].offset = main_offset; 303 } 304 } 305 306 //Pass input thumbnail buffer info to encoder. 307 //Note: In this version thumb_stream = main_stream 308 if (m_bThumbnailNeeded == TRUE) { 309 pStreamMem = main_stream->getStreamBufs(); 310 if (pStreamMem == NULL) { 311 ALOGE("%s: cannot get stream bufs from thumb stream", __func__); 312 ret = BAD_VALUE; 313 goto on_error; 314 } 315 cam_frame_len_offset_t thumb_offset; 316 memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t)); 317 main_stream->getFrameOffset(thumb_offset); 318 encode_parm.num_tmb_bufs = pStreamMem->getCnt(); 319 for (int i = 0; i < pStreamMem->getCnt(); i++) { 320 if (pStreamMem != NULL) { 321 encode_parm.src_thumb_buf[i].index = i; 322 encode_parm.src_thumb_buf[i].buf_size = pStreamMem->getSize(i); 323 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i); 324 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i); 325 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV; 326 encode_parm.src_thumb_buf[i].offset = thumb_offset; 327 } 328 } 329 } 330 331 //Pass output jpeg buffer info to encoder. 332 //mJpegMem is allocated by framework. 333 encode_parm.num_dst_bufs = 1; 334 encode_parm.dest_buf[0].index = 0; 335 encode_parm.dest_buf[0].buf_size = mJpegMem->getSize( 336 jpeg_settings->out_buf_index); 337 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr( 338 jpeg_settings->out_buf_index); 339 encode_parm.dest_buf[0].fd = mJpegMem->getFd( 340 jpeg_settings->out_buf_index); 341 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV; 342 encode_parm.dest_buf[0].offset = main_offset; 343 344 ALOGV("%s : X", __func__); 345 return NO_ERROR; 346 347 on_error: 348 349 ALOGV("%s : X with error %d", __func__, ret); 350 return ret; 351 } 352 353 /*=========================================================================== 354 * FUNCTION : processData 355 * 356 * DESCRIPTION: enqueue data into dataProc thread 357 * 358 * PARAMETERS : 359 * @frame : process frame received from mm-camera-interface 360 * 361 * RETURN : int32_t type of status 362 * NO_ERROR -- success 363 * none-zero failure code 364 * 365 * NOTE : depends on if offline reprocess is needed, received frame will 366 * be sent to either input queue of postprocess or jpeg encoding 367 *==========================================================================*/ 368 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame) 369 { 370 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData; 371 if (hal_obj->needReprocess()) { 372 pthread_mutex_lock(&mReprocJobLock); 373 // enqueu to post proc input queue 374 m_inputPPQ.enqueue((void *)frame); 375 if (!(m_inputMetaQ.isEmpty())) { 376 ALOGV("%s: meta queue is not empty, do next job", __func__); 377 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 378 } 379 pthread_mutex_unlock(&mReprocJobLock); 380 } else { 381 ALOGD("%s: no need offline reprocess, sending to jpeg encoding", __func__); 382 qcamera_jpeg_data_t *jpeg_job = 383 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t)); 384 if (jpeg_job == NULL) { 385 ALOGE("%s: No memory for jpeg job", __func__); 386 return NO_MEMORY; 387 } 388 389 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t)); 390 jpeg_job->src_frame = frame; 391 392 // enqueu to jpeg input queue 393 m_inputJpegQ.enqueue((void *)jpeg_job); 394 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 395 } 396 397 return NO_ERROR; 398 } 399 400 /*=========================================================================== 401 * FUNCTION : processPPMetadata 402 * 403 * DESCRIPTION: enqueue data into dataProc thread 404 * 405 * PARAMETERS : 406 * @frame : process metadata frame received from pic channel 407 * 408 * RETURN : int32_t type of status 409 * NO_ERROR -- success 410 * none-zero failure code 411 * 412 *==========================================================================*/ 413 int32_t QCamera3PostProcessor::processPPMetadata(metadata_buffer_t *reproc_meta) 414 { 415 pthread_mutex_lock(&mReprocJobLock); 416 // enqueue to metadata input queue 417 m_inputMetaQ.enqueue((void *)reproc_meta); 418 if (!(m_inputPPQ.isEmpty())) { 419 ALOGI("%s: pp queue is not empty, do next job", __func__); 420 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 421 } else { 422 ALOGI("%s: pp queue is empty, not calling do next job", __func__); 423 } 424 pthread_mutex_unlock(&mReprocJobLock); 425 return NO_ERROR; 426 } 427 428 /*=========================================================================== 429 * FUNCTION : processJpegSettingData 430 * 431 * DESCRIPTION: enqueue jpegSetting into dataProc thread 432 * 433 * PARAMETERS : 434 * @jpeg_settings : jpeg settings data received from pic channel 435 * 436 * RETURN : int32_t type of status 437 * NO_ERROR -- success 438 * none-zero failure code 439 * 440 *==========================================================================*/ 441 int32_t QCamera3PostProcessor::processJpegSettingData( 442 jpeg_settings_t *jpeg_settings) 443 { 444 if (!jpeg_settings) { 445 ALOGE("%s: invalid jpeg settings pointer", __func__); 446 return -EINVAL; 447 } 448 return m_jpegSettingsQ.enqueue((void *)jpeg_settings); 449 } 450 451 /*=========================================================================== 452 * FUNCTION : processRawData 453 * 454 * DESCRIPTION: enqueue raw data into dataProc thread 455 * 456 * PARAMETERS : 457 * @frame : process frame received from mm-camera-interface 458 * 459 * RETURN : int32_t type of status 460 * NO_ERROR -- success 461 * none-zero failure code 462 *==========================================================================*/ 463 int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame) 464 { 465 // enqueu to raw input queue 466 m_inputRawQ.enqueue((void *)frame); 467 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 468 return NO_ERROR; 469 } 470 471 /*=========================================================================== 472 * FUNCTION : processPPData 473 * 474 * DESCRIPTION: process received frame after reprocess. 475 * 476 * PARAMETERS : 477 * @frame : received frame from reprocess channel. 478 * 479 * RETURN : int32_t type of status 480 * NO_ERROR -- success 481 * none-zero failure code 482 * 483 * NOTE : The frame after reprocess need to send to jpeg encoding. 484 *==========================================================================*/ 485 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame) 486 { 487 qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue(); 488 jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue(); 489 490 if (job == NULL || job->src_frame == NULL) { 491 ALOGE("%s: Cannot find reprocess job", __func__); 492 return BAD_VALUE; 493 } 494 if (jpeg_settings == NULL) { 495 ALOGE("%s: Cannot find jpeg settings", __func__); 496 return BAD_VALUE; 497 } 498 499 qcamera_jpeg_data_t *jpeg_job = 500 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t)); 501 if (jpeg_job == NULL) { 502 ALOGE("%s: No memory for jpeg job", __func__); 503 return NO_MEMORY; 504 } 505 506 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t)); 507 jpeg_job->src_frame = frame; 508 jpeg_job->src_reproc_frame = job->src_frame; 509 jpeg_job->metadata = job->metadata; 510 jpeg_job->jpeg_settings = jpeg_settings; 511 512 // free pp job buf 513 free(job); 514 515 // enqueu reprocessed frame to jpeg input queue 516 m_inputJpegQ.enqueue((void *)jpeg_job); 517 518 // wait up data proc thread 519 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 520 521 return NO_ERROR; 522 } 523 524 /*=========================================================================== 525 * FUNCTION : findJpegJobByJobId 526 * 527 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID 528 * 529 * PARAMETERS : 530 * @jobId : job Id of the job 531 * 532 * RETURN : ptr to a jpeg job struct. NULL if not found. 533 * 534 * NOTE : Currently only one job is sending to mm-jpeg-interface for jpeg 535 * encoding. Therefore simply dequeue from the ongoing Jpeg Queue 536 * will serve the purpose to find the jpeg job. 537 *==========================================================================*/ 538 qcamera_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId) 539 { 540 qcamera_jpeg_data_t * job = NULL; 541 if (jobId == 0) { 542 ALOGE("%s: not a valid jpeg jobId", __func__); 543 return NULL; 544 } 545 546 // currely only one jpeg job ongoing, so simply dequeue the head 547 job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue(); 548 return job; 549 } 550 551 /*=========================================================================== 552 * FUNCTION : releasePPInputData 553 * 554 * DESCRIPTION: callback function to release post process input data node 555 * 556 * PARAMETERS : 557 * @data : ptr to post process input data 558 * @user_data : user data ptr (QCamera3Reprocessor) 559 * 560 * RETURN : None 561 *==========================================================================*/ 562 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data) 563 { 564 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data; 565 if (NULL != pme) { 566 pme->releaseSuperBuf((mm_camera_super_buf_t *)data); 567 } 568 } 569 570 /*=========================================================================== 571 * FUNCTION : releaseMetaData 572 * 573 * DESCRIPTION: callback function to release meta data node 574 * 575 * PARAMETERS : 576 * @data : ptr to post process input data 577 * @user_data : user data ptr (QCamera3Reprocessor) 578 * 579 * RETURN : None 580 *==========================================================================*/ 581 void QCamera3PostProcessor::releaseMetaData(void *data, void * /*user_data*/) 582 { 583 metadata_buffer_t *metadata = (metadata_buffer_t *)data; 584 if (metadata != NULL) 585 free(metadata); 586 } 587 588 /*=========================================================================== 589 * FUNCTION : releaseJpegSetting 590 * 591 * DESCRIPTION: callback function to release meta data node 592 * 593 * PARAMETERS : 594 * @data : ptr to post process input data 595 * @user_data : user data ptr (QCamera3Reprocessor) 596 * 597 * RETURN : None 598 *==========================================================================*/ 599 void QCamera3PostProcessor::releaseJpegSetting(void *data, void * /*user_data*/) 600 { 601 jpeg_settings_t *jpegSetting = (jpeg_settings_t *)data; 602 if (jpegSetting != NULL) 603 free(jpegSetting); 604 } 605 606 /*=========================================================================== 607 * FUNCTION : releaseJpegData 608 * 609 * DESCRIPTION: callback function to release jpeg job node 610 * 611 * PARAMETERS : 612 * @data : ptr to ongoing jpeg job data 613 * @user_data : user data ptr (QCamera3Reprocessor) 614 * 615 * RETURN : None 616 *==========================================================================*/ 617 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data) 618 { 619 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data; 620 if (NULL != pme) { 621 pme->releaseJpegJobData((qcamera_jpeg_data_t *)data); 622 } 623 } 624 625 /*=========================================================================== 626 * FUNCTION : releaseOngoingPPData 627 * 628 * DESCRIPTION: callback function to release ongoing postprocess job node 629 * 630 * PARAMETERS : 631 * @data : ptr to onging postprocess job 632 * @user_data : user data ptr (QCamera3Reprocessor) 633 * 634 * RETURN : None 635 *==========================================================================*/ 636 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data) 637 { 638 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data; 639 if (NULL != pme) { 640 qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data; 641 if (NULL != pp_job->src_frame) { 642 pme->releaseSuperBuf(pp_job->src_frame); 643 free(pp_job->src_frame); 644 free(pp_job->metadata); 645 pp_job->src_frame = NULL; 646 pp_job->metadata = NULL; 647 } 648 } 649 } 650 651 /*=========================================================================== 652 * FUNCTION : releaseSuperBuf 653 * 654 * DESCRIPTION: function to release a superbuf frame by returning back to kernel 655 * 656 * PARAMETERS : 657 * @super_buf : ptr to the superbuf frame 658 * 659 * RETURN : None 660 *==========================================================================*/ 661 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf) 662 { 663 if (NULL != super_buf) { 664 if (m_parent != NULL) { 665 m_parent->bufDone(super_buf); 666 } 667 } 668 } 669 670 /*=========================================================================== 671 * FUNCTION : releaseJpegJobData 672 * 673 * DESCRIPTION: function to release internal resources in jpeg job struct 674 * 675 * PARAMETERS : 676 * @job : ptr to jpeg job struct 677 * 678 * RETURN : None 679 * 680 * NOTE : original source frame need to be queued back to kernel for 681 * future use. Output buf of jpeg job need to be released since 682 * it's allocated for each job. Exif object need to be deleted. 683 *==========================================================================*/ 684 void QCamera3PostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job) 685 { 686 ALOGV("%s: E", __func__); 687 if (NULL != job) { 688 if (NULL != job->src_reproc_frame) { 689 free(job->src_reproc_frame); 690 job->src_reproc_frame = NULL; 691 } 692 693 if (NULL != job->src_frame) { 694 free(job->src_frame); 695 job->src_frame = NULL; 696 } 697 698 if (NULL != job->metadata) { 699 free(job->metadata); 700 job->metadata = NULL; 701 } 702 703 if (NULL != job->jpeg_settings) { 704 free(job->jpeg_settings); 705 job->jpeg_settings = NULL; 706 } 707 } 708 ALOGV("%s: X", __func__); 709 } 710 711 /*=========================================================================== 712 * FUNCTION : getColorfmtFromImgFmt 713 * 714 * DESCRIPTION: function to return jpeg color format based on its image format 715 * 716 * PARAMETERS : 717 * @img_fmt : image format 718 * 719 * RETURN : jpeg color format that can be understandable by omx lib 720 *==========================================================================*/ 721 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt) 722 { 723 switch (img_fmt) { 724 case CAM_FORMAT_YUV_420_NV21: 725 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 726 case CAM_FORMAT_YUV_420_NV21_ADRENO: 727 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 728 case CAM_FORMAT_YUV_420_NV12: 729 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 730 case CAM_FORMAT_YUV_420_YV12: 731 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 732 case CAM_FORMAT_YUV_422_NV61: 733 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1; 734 case CAM_FORMAT_YUV_422_NV16: 735 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1; 736 default: 737 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 738 } 739 } 740 741 /*=========================================================================== 742 * FUNCTION : getJpegImgTypeFromImgFmt 743 * 744 * DESCRIPTION: function to return jpeg encode image type based on its image format 745 * 746 * PARAMETERS : 747 * @img_fmt : image format 748 * 749 * RETURN : return jpeg source image format (YUV or Bitstream) 750 *==========================================================================*/ 751 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt) 752 { 753 switch (img_fmt) { 754 case CAM_FORMAT_YUV_420_NV21: 755 case CAM_FORMAT_YUV_420_NV21_ADRENO: 756 case CAM_FORMAT_YUV_420_NV12: 757 case CAM_FORMAT_YUV_420_YV12: 758 case CAM_FORMAT_YUV_422_NV61: 759 case CAM_FORMAT_YUV_422_NV16: 760 return MM_JPEG_FMT_YUV; 761 default: 762 return MM_JPEG_FMT_YUV; 763 } 764 } 765 766 /*=========================================================================== 767 * FUNCTION : encodeData 768 * 769 * DESCRIPTION: function to prepare encoding job information and send to 770 * mm-jpeg-interface to do the encoding job 771 * 772 * PARAMETERS : 773 * @jpeg_job_data : ptr to a struct saving job related information 774 * @needNewSess : flag to indicate if a new jpeg encoding session need 775 * to be created. After creation, this flag will be toggled 776 * 777 * RETURN : int32_t type of status 778 * NO_ERROR -- success 779 * none-zero failure code 780 *==========================================================================*/ 781 int32_t QCamera3PostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data, 782 uint8_t &needNewSess) 783 { 784 ALOGV("%s : E", __func__); 785 int32_t ret = NO_ERROR; 786 mm_jpeg_job_t jpg_job; 787 uint32_t jobId = 0; 788 QCamera3Stream *main_stream = NULL; 789 mm_camera_buf_def_t *main_frame = NULL; 790 QCamera3Stream *thumb_stream = NULL; 791 mm_camera_buf_def_t *thumb_frame = NULL; 792 QCamera3Channel *srcChannel = NULL; 793 mm_camera_super_buf_t *recvd_frame = NULL; 794 metadata_buffer_t *metadata = NULL; 795 jpeg_settings_t *jpeg_settings = NULL; 796 QCamera3HardwareInterface* hal_obj = NULL; 797 798 799 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData; 800 recvd_frame = jpeg_job_data->src_frame; 801 metadata = jpeg_job_data->metadata; 802 jpeg_settings = jpeg_job_data->jpeg_settings; 803 804 QCamera3Channel *pChannel = NULL; 805 // first check picture channel 806 if (m_parent != NULL && 807 m_parent->getMyHandle() == recvd_frame->ch_id) { 808 pChannel = m_parent; 809 } 810 // check reprocess channel if not found 811 if (pChannel == NULL) { 812 if (m_pReprocChannel != NULL && 813 m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) { 814 pChannel = m_pReprocChannel; 815 } 816 } 817 818 srcChannel = pChannel; 819 820 if (srcChannel == NULL) { 821 ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here", 822 __func__, recvd_frame->ch_id); 823 return BAD_VALUE; 824 } 825 826 // find snapshot frame and thumnail frame 827 //Note: In this version we will receive only snapshot frame. 828 for (int i = 0; i < recvd_frame->num_bufs; i++) { 829 QCamera3Stream *srcStream = 830 srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id); 831 if (srcStream != NULL) { 832 switch (srcStream->getMyType()) { 833 case CAM_STREAM_TYPE_SNAPSHOT: 834 case CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT: 835 case CAM_STREAM_TYPE_OFFLINE_PROC: 836 main_stream = srcStream; 837 main_frame = recvd_frame->bufs[i]; 838 break; 839 case CAM_STREAM_TYPE_PREVIEW: 840 case CAM_STREAM_TYPE_POSTVIEW: 841 thumb_stream = srcStream; 842 thumb_frame = recvd_frame->bufs[i]; 843 break; 844 default: 845 break; 846 } 847 } 848 } 849 850 if(NULL == main_frame){ 851 ALOGE("%s : Main frame is NULL", __func__); 852 return BAD_VALUE; 853 } 854 855 QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info; 856 if (NULL == memObj) { 857 ALOGE("%s : Memeory Obj of main frame is NULL", __func__); 858 return NO_MEMORY; 859 } 860 861 // clean and invalidate cache ops through mem obj of the frame 862 memObj->cleanInvalidateCache(main_frame->buf_idx); 863 864 if (thumb_frame != NULL) { 865 QCamera3Memory *thumb_memObj = (QCamera3Memory *)thumb_frame->mem_info; 866 if (NULL != thumb_memObj) { 867 // clean and invalidate cache ops through mem obj of the frame 868 thumb_memObj->cleanInvalidateCache(thumb_frame->buf_idx); 869 } 870 } 871 872 if (mJpegClientHandle <= 0) { 873 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__); 874 return UNKNOWN_ERROR; 875 } 876 877 ALOGD("%s: Need new session?:%d",__func__, needNewSess); 878 if (needNewSess) { 879 //creating a new session, so we must destroy the old one 880 if ( 0 < mJpegSessionId ) { 881 ret = mJpegHandle.destroy_session(mJpegSessionId); 882 if (ret != NO_ERROR) { 883 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d", 884 __func__, mJpegSessionId); 885 return ret; 886 } 887 mJpegSessionId = 0; 888 } 889 // create jpeg encoding session 890 mm_jpeg_encode_params_t encodeParam; 891 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t)); 892 893 getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings); 894 ALOGD("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__, 895 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs); 896 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId); 897 if (ret != NO_ERROR) { 898 ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret); 899 return ret; 900 } 901 needNewSess = FALSE; 902 } 903 904 // Fill in new job 905 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t)); 906 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE; 907 jpg_job.encode_job.session_id = mJpegSessionId; 908 jpg_job.encode_job.src_index = main_frame->buf_idx; 909 jpg_job.encode_job.dst_index = 0; 910 911 cam_rect_t crop; 912 memset(&crop, 0, sizeof(cam_rect_t)); 913 //TBD_later - Zoom event removed in stream 914 //main_stream->getCropInfo(crop); 915 916 cam_dimension_t src_dim; 917 memset(&src_dim, 0, sizeof(cam_dimension_t)); 918 main_stream->getFrameDimension(src_dim); 919 920 cam_dimension_t dst_dim; 921 memset(&dst_dim, 0, sizeof(cam_dimension_t)); 922 srcChannel->getStreamByIndex(0)->getFrameDimension(dst_dim); 923 924 // main dim 925 jpg_job.encode_job.main_dim.src_dim = src_dim; 926 jpg_job.encode_job.main_dim.dst_dim = dst_dim; 927 jpg_job.encode_job.main_dim.crop = crop; 928 929 // get exif data 930 if (m_pJpegExifObj != NULL) { 931 delete m_pJpegExifObj; 932 m_pJpegExifObj = NULL; 933 } 934 m_pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings); 935 if (m_pJpegExifObj != NULL) { 936 jpg_job.encode_job.exif_info.exif_data = m_pJpegExifObj->getEntries(); 937 jpg_job.encode_job.exif_info.numOfEntries = 938 m_pJpegExifObj->getNumOfEntries(); 939 } 940 // thumbnail dim 941 ALOGD("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded); 942 if (m_bThumbnailNeeded == TRUE) { 943 if (thumb_stream == NULL) { 944 // need jpeg thumbnail, but no postview/preview stream exists 945 // we use the main stream/frame to encode thumbnail 946 thumb_stream = main_stream; 947 thumb_frame = main_frame; 948 } 949 memset(&crop, 0, sizeof(cam_rect_t)); 950 //TBD_later - Zoom event removed in stream 951 //thumb_stream->getCropInfo(crop); 952 jpg_job.encode_job.thumb_dim.dst_dim = 953 jpeg_settings->thumbnail_size; 954 955 if (!hal_obj->needRotationReprocess()) { 956 memset(&src_dim, 0, sizeof(cam_dimension_t)); 957 thumb_stream->getFrameDimension(src_dim); 958 jpg_job.encode_job.rotation = 959 jpeg_settings->jpeg_orientation; 960 ALOGD("%s: jpeg rotation is set to %d", __func__, 961 jpg_job.encode_job.rotation); 962 } else if (jpeg_settings->jpeg_orientation == 90 || 963 jpeg_settings->jpeg_orientation == 270) { 964 //swap the thumbnail destination width and height if it has already been rotated 965 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width; 966 jpg_job.encode_job.thumb_dim.dst_dim.width = 967 jpg_job.encode_job.thumb_dim.dst_dim.height; 968 jpg_job.encode_job.thumb_dim.dst_dim.height = temp; 969 } 970 jpg_job.encode_job.thumb_dim.src_dim = src_dim; 971 jpg_job.encode_job.thumb_dim.crop = crop; 972 jpg_job.encode_job.thumb_index = thumb_frame->buf_idx; 973 } 974 975 if (metadata != NULL) { 976 //Fill in the metadata passed as parameter 977 jpg_job.encode_job.p_metadata_v3 = metadata; 978 } else { 979 ALOGE("%s: Metadata is null", __func__); 980 } 981 //Not required here 982 //jpg_job.encode_job.cam_exif_params = m_parent->mExifParams; 983 //Start jpeg encoding 984 ret = mJpegHandle.start_job(&jpg_job, &jobId); 985 if (ret == NO_ERROR) { 986 // remember job info 987 jpeg_job_data->jobId = jobId; 988 } 989 990 ALOGV("%s : X", __func__); 991 return ret; 992 } 993 994 /*=========================================================================== 995 * FUNCTION : dataProcessRoutine 996 * 997 * DESCRIPTION: data process routine that handles input data either from input 998 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do 999 * reprocess. 1000 * 1001 * PARAMETERS : 1002 * @data : user data ptr (QCamera3PostProcessor) 1003 * 1004 * RETURN : None 1005 *==========================================================================*/ 1006 void *QCamera3PostProcessor::dataProcessRoutine(void *data) 1007 { 1008 int running = 1; 1009 int ret; 1010 uint8_t is_active = FALSE; 1011 uint8_t needNewSess = TRUE; 1012 mm_camera_super_buf_t *pp_frame = NULL; 1013 metadata_buffer_t *meta_buffer = NULL; 1014 ALOGV("%s: E", __func__); 1015 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data; 1016 QCameraCmdThread *cmdThread = &pme->m_dataProcTh; 1017 cmdThread->setName("cam_data_proc"); 1018 1019 do { 1020 do { 1021 ret = cam_sem_wait(&cmdThread->cmd_sem); 1022 if (ret != 0 && errno != EINVAL) { 1023 ALOGE("%s: cam_sem_wait error (%s)", 1024 __func__, strerror(errno)); 1025 return NULL; 1026 } 1027 } while (ret != 0); 1028 1029 // we got notified about new cmd avail in cmd queue 1030 camera_cmd_type_t cmd = cmdThread->getCmd(); 1031 switch (cmd) { 1032 case CAMERA_CMD_TYPE_START_DATA_PROC: 1033 ALOGD("%s: start data proc", __func__); 1034 is_active = TRUE; 1035 needNewSess = TRUE; 1036 1037 pme->m_ongoingPPQ.init(); 1038 pme->m_inputJpegQ.init(); 1039 pme->m_inputPPQ.init(); 1040 pme->m_inputRawQ.init(); 1041 pme->m_inputMetaQ.init(); 1042 pme->m_ongoingJpegQ.init(); 1043 pme->m_jpegSettingsQ.init(); 1044 1045 break; 1046 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 1047 { 1048 ALOGD("%s: stop data proc", __func__); 1049 is_active = FALSE; 1050 1051 // cancel all ongoing jpeg jobs 1052 qcamera_jpeg_data_t *jpeg_job = 1053 (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1054 while (jpeg_job != NULL) { 1055 pme->mJpegHandle.abort_job(jpeg_job->jobId); 1056 1057 pme->releaseJpegJobData(jpeg_job); 1058 free(jpeg_job); 1059 1060 jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1061 } 1062 1063 // destroy jpeg encoding session 1064 if ( 0 < pme->mJpegSessionId ) { 1065 pme->mJpegHandle.destroy_session(pme->mJpegSessionId); 1066 pme->mJpegSessionId = 0; 1067 } 1068 1069 // free jpeg exif obj 1070 if (pme->m_pJpegExifObj != NULL) { 1071 delete pme->m_pJpegExifObj; 1072 pme->m_pJpegExifObj = NULL; 1073 } 1074 needNewSess = TRUE; 1075 1076 // flush ongoing postproc Queue 1077 pme->m_ongoingPPQ.flush(); 1078 1079 // flush input jpeg Queue 1080 pme->m_inputJpegQ.flush(); 1081 1082 // flush input Postproc Queue 1083 pme->m_inputPPQ.flush(); 1084 1085 // flush input raw Queue 1086 pme->m_inputRawQ.flush(); 1087 1088 pme->m_inputMetaQ.flush(); 1089 1090 // signal cmd is completed 1091 cam_sem_post(&cmdThread->sync_sem); 1092 } 1093 break; 1094 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 1095 { 1096 ALOGD("%s: Do next job, active is %d", __func__, is_active); 1097 if (is_active == TRUE) { 1098 // check if there is any ongoing jpeg jobs 1099 if (pme->m_ongoingJpegQ.isEmpty()) { 1100 ALOGI("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__); 1101 // no ongoing jpeg job, we are fine to send jpeg encoding job 1102 qcamera_jpeg_data_t *jpeg_job = 1103 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 1104 1105 if (NULL != jpeg_job) { 1106 // add into ongoing jpeg job Q 1107 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job); 1108 ret = pme->encodeData(jpeg_job, needNewSess); 1109 if (NO_ERROR != ret) { 1110 // dequeue the last one 1111 pme->m_ongoingJpegQ.dequeue(false); 1112 1113 pme->releaseJpegJobData(jpeg_job); 1114 free(jpeg_job); 1115 } 1116 } 1117 } 1118 ALOGD("%s: dequeuing pp frame", __func__); 1119 pp_frame = 1120 (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 1121 meta_buffer = 1122 (metadata_buffer_t *)pme->m_inputMetaQ.dequeue(); 1123 if (NULL != pp_frame && NULL != meta_buffer) { 1124 qcamera_pp_data_t *pp_job = 1125 (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t)); 1126 if (pp_job != NULL) { 1127 memset(pp_job, 0, sizeof(qcamera_pp_data_t)); 1128 if (pme->m_pReprocChannel != NULL) { 1129 // add into ongoing PP job Q 1130 pp_job->src_frame = pp_frame; 1131 pp_job->metadata = meta_buffer; 1132 pme->m_ongoingPPQ.enqueue((void *)pp_job); 1133 ret = pme->m_pReprocChannel->doReprocessOffline(pp_frame, meta_buffer); 1134 if (NO_ERROR != ret) { 1135 // remove from ongoing PP job Q 1136 pme->m_ongoingPPQ.dequeue(false); 1137 } 1138 } else { 1139 ALOGE("%s: Reprocess channel is NULL", __func__); 1140 ret = -1; 1141 } 1142 } else { 1143 ALOGE("%s: no mem for qcamera_pp_data_t", __func__); 1144 ret = -1; 1145 } 1146 1147 if (0 != ret) { 1148 // free pp_job 1149 if (pp_job != NULL) { 1150 free(pp_job); 1151 } 1152 // free frame 1153 if (pp_frame != NULL) { 1154 pme->releaseSuperBuf(pp_frame); 1155 free(pp_frame); 1156 } 1157 } 1158 } 1159 } else { 1160 // not active, simply return buf and do no op 1161 mm_camera_super_buf_t *super_buf; 1162 qcamera_jpeg_data_t *jpeg_job = 1163 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 1164 if (NULL != jpeg_job) { 1165 free(jpeg_job); 1166 } 1167 super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 1168 if (NULL != super_buf) { 1169 pme->releaseSuperBuf(super_buf); 1170 free(super_buf); 1171 } 1172 super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 1173 if (NULL != super_buf) { 1174 pme->releaseSuperBuf(super_buf); 1175 free(super_buf); 1176 } 1177 super_buf = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue(); 1178 if (NULL != super_buf) { 1179 pme->releaseSuperBuf(super_buf); 1180 free(super_buf); 1181 } 1182 } 1183 } 1184 break; 1185 case CAMERA_CMD_TYPE_EXIT: 1186 running = 0; 1187 break; 1188 default: 1189 break; 1190 } 1191 } while (running); 1192 ALOGV("%s: X", __func__); 1193 return NULL; 1194 } 1195 1196 /*=========================================================================== 1197 * FUNCTION : QCamera3Exif 1198 * 1199 * DESCRIPTION: constructor of QCamera3Exif 1200 * 1201 * PARAMETERS : None 1202 * 1203 * RETURN : None 1204 *==========================================================================*/ 1205 QCamera3Exif::QCamera3Exif() 1206 : m_nNumEntries(0) 1207 { 1208 memset(m_Entries, 0, sizeof(m_Entries)); 1209 } 1210 1211 /*=========================================================================== 1212 * FUNCTION : ~QCamera3Exif 1213 * 1214 * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr. 1215 * 1216 * PARAMETERS : None 1217 * 1218 * RETURN : None 1219 *==========================================================================*/ 1220 QCamera3Exif::~QCamera3Exif() 1221 { 1222 for (uint32_t i = 0; i < m_nNumEntries; i++) { 1223 switch (m_Entries[i].tag_entry.type) { 1224 case EXIF_BYTE: 1225 { 1226 if (m_Entries[i].tag_entry.count > 1 && 1227 m_Entries[i].tag_entry.data._bytes != NULL) { 1228 free(m_Entries[i].tag_entry.data._bytes); 1229 m_Entries[i].tag_entry.data._bytes = NULL; 1230 } 1231 } 1232 break; 1233 case EXIF_ASCII: 1234 { 1235 if (m_Entries[i].tag_entry.data._ascii != NULL) { 1236 free(m_Entries[i].tag_entry.data._ascii); 1237 m_Entries[i].tag_entry.data._ascii = NULL; 1238 } 1239 } 1240 break; 1241 case EXIF_SHORT: 1242 { 1243 if (m_Entries[i].tag_entry.count > 1 && 1244 m_Entries[i].tag_entry.data._shorts != NULL) { 1245 free(m_Entries[i].tag_entry.data._shorts); 1246 m_Entries[i].tag_entry.data._shorts = NULL; 1247 } 1248 } 1249 break; 1250 case EXIF_LONG: 1251 { 1252 if (m_Entries[i].tag_entry.count > 1 && 1253 m_Entries[i].tag_entry.data._longs != NULL) { 1254 free(m_Entries[i].tag_entry.data._longs); 1255 m_Entries[i].tag_entry.data._longs = NULL; 1256 } 1257 } 1258 break; 1259 case EXIF_RATIONAL: 1260 { 1261 if (m_Entries[i].tag_entry.count > 1 && 1262 m_Entries[i].tag_entry.data._rats != NULL) { 1263 free(m_Entries[i].tag_entry.data._rats); 1264 m_Entries[i].tag_entry.data._rats = NULL; 1265 } 1266 } 1267 break; 1268 case EXIF_UNDEFINED: 1269 { 1270 if (m_Entries[i].tag_entry.data._undefined != NULL) { 1271 free(m_Entries[i].tag_entry.data._undefined); 1272 m_Entries[i].tag_entry.data._undefined = NULL; 1273 } 1274 } 1275 break; 1276 case EXIF_SLONG: 1277 { 1278 if (m_Entries[i].tag_entry.count > 1 && 1279 m_Entries[i].tag_entry.data._slongs != NULL) { 1280 free(m_Entries[i].tag_entry.data._slongs); 1281 m_Entries[i].tag_entry.data._slongs = NULL; 1282 } 1283 } 1284 break; 1285 case EXIF_SRATIONAL: 1286 { 1287 if (m_Entries[i].tag_entry.count > 1 && 1288 m_Entries[i].tag_entry.data._srats != NULL) { 1289 free(m_Entries[i].tag_entry.data._srats); 1290 m_Entries[i].tag_entry.data._srats = NULL; 1291 } 1292 } 1293 break; 1294 default: 1295 ALOGE("%s: Error, Unknown type",__func__); 1296 break; 1297 } 1298 } 1299 } 1300 1301 /*=========================================================================== 1302 * FUNCTION : addEntry 1303 * 1304 * DESCRIPTION: function to add an entry to exif data 1305 * 1306 * PARAMETERS : 1307 * @tagid : exif tag ID 1308 * @type : data type 1309 * @count : number of data in uint of its type 1310 * @data : input data ptr 1311 * 1312 * RETURN : int32_t type of status 1313 * NO_ERROR -- success 1314 * none-zero failure code 1315 *==========================================================================*/ 1316 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid, 1317 exif_tag_type_t type, 1318 uint32_t count, 1319 void *data) 1320 { 1321 int32_t rc = NO_ERROR; 1322 if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) { 1323 ALOGE("%s: Number of entries exceeded limit", __func__); 1324 return NO_MEMORY; 1325 } 1326 1327 m_Entries[m_nNumEntries].tag_id = tagid; 1328 m_Entries[m_nNumEntries].tag_entry.type = type; 1329 m_Entries[m_nNumEntries].tag_entry.count = count; 1330 m_Entries[m_nNumEntries].tag_entry.copy = 1; 1331 switch (type) { 1332 case EXIF_BYTE: 1333 { 1334 if (count > 1) { 1335 uint8_t *values = (uint8_t *)malloc(count); 1336 if (values == NULL) { 1337 ALOGE("%s: No memory for byte array", __func__); 1338 rc = NO_MEMORY; 1339 } else { 1340 memcpy(values, data, count); 1341 m_Entries[m_nNumEntries].tag_entry.data._bytes = values; 1342 } 1343 } else { 1344 m_Entries[m_nNumEntries].tag_entry.data._byte = 1345 *(uint8_t *)data; 1346 } 1347 } 1348 break; 1349 case EXIF_ASCII: 1350 { 1351 char *str = NULL; 1352 str = (char *)malloc(count + 1); 1353 if (str == NULL) { 1354 ALOGE("%s: No memory for ascii string", __func__); 1355 rc = NO_MEMORY; 1356 } else { 1357 memset(str, 0, count + 1); 1358 memcpy(str, data, count); 1359 m_Entries[m_nNumEntries].tag_entry.data._ascii = str; 1360 } 1361 } 1362 break; 1363 case EXIF_SHORT: 1364 { 1365 if (count > 1) { 1366 uint16_t *values = 1367 (uint16_t *)malloc(count * sizeof(uint16_t)); 1368 if (values == NULL) { 1369 ALOGE("%s: No memory for short array", __func__); 1370 rc = NO_MEMORY; 1371 } else { 1372 memcpy(values, data, count * sizeof(uint16_t)); 1373 m_Entries[m_nNumEntries].tag_entry.data._shorts =values; 1374 } 1375 } else { 1376 m_Entries[m_nNumEntries].tag_entry.data._short = 1377 *(uint16_t *)data; 1378 } 1379 } 1380 break; 1381 case EXIF_LONG: 1382 { 1383 if (count > 1) { 1384 uint32_t *values = 1385 (uint32_t *)malloc(count * sizeof(uint32_t)); 1386 if (values == NULL) { 1387 ALOGE("%s: No memory for long array", __func__); 1388 rc = NO_MEMORY; 1389 } else { 1390 memcpy(values, data, count * sizeof(uint32_t)); 1391 m_Entries[m_nNumEntries].tag_entry.data._longs = values; 1392 } 1393 } else { 1394 m_Entries[m_nNumEntries].tag_entry.data._long = 1395 *(uint32_t *)data; 1396 } 1397 } 1398 break; 1399 case EXIF_RATIONAL: 1400 { 1401 if (count > 1) { 1402 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t)); 1403 if (values == NULL) { 1404 ALOGE("%s: No memory for rational array", __func__); 1405 rc = NO_MEMORY; 1406 } else { 1407 memcpy(values, data, count * sizeof(rat_t)); 1408 m_Entries[m_nNumEntries].tag_entry.data._rats = values; 1409 } 1410 } else { 1411 m_Entries[m_nNumEntries].tag_entry.data._rat = 1412 *(rat_t *)data; 1413 } 1414 } 1415 break; 1416 case EXIF_UNDEFINED: 1417 { 1418 uint8_t *values = (uint8_t *)malloc(count); 1419 if (values == NULL) { 1420 ALOGE("%s: No memory for undefined array", __func__); 1421 rc = NO_MEMORY; 1422 } else { 1423 memcpy(values, data, count); 1424 m_Entries[m_nNumEntries].tag_entry.data._undefined = values; 1425 } 1426 } 1427 break; 1428 case EXIF_SLONG: 1429 { 1430 if (count > 1) { 1431 int32_t *values = 1432 (int32_t *)malloc(count * sizeof(int32_t)); 1433 if (values == NULL) { 1434 ALOGE("%s: No memory for signed long array", __func__); 1435 rc = NO_MEMORY; 1436 } else { 1437 memcpy(values, data, count * sizeof(int32_t)); 1438 m_Entries[m_nNumEntries].tag_entry.data._slongs =values; 1439 } 1440 } else { 1441 m_Entries[m_nNumEntries].tag_entry.data._slong = 1442 *(int32_t *)data; 1443 } 1444 } 1445 break; 1446 case EXIF_SRATIONAL: 1447 { 1448 if (count > 1) { 1449 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t)); 1450 if (values == NULL) { 1451 ALOGE("%s: No memory for sign rational array",__func__); 1452 rc = NO_MEMORY; 1453 } else { 1454 memcpy(values, data, count * sizeof(srat_t)); 1455 m_Entries[m_nNumEntries].tag_entry.data._srats = values; 1456 } 1457 } else { 1458 m_Entries[m_nNumEntries].tag_entry.data._srat = 1459 *(srat_t *)data; 1460 } 1461 } 1462 break; 1463 default: 1464 ALOGE("%s: Error, Unknown type",__func__); 1465 break; 1466 } 1467 1468 // Increase number of entries 1469 m_nNumEntries++; 1470 return rc; 1471 } 1472 1473 }; // namespace qcamera 1474