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