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