QCamera3PostProc.cpp revision 34a6e88cee59495adcf1437d027c105171738a07
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 40namespace 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 *==========================================================================*/ 52QCamera3PostProcessor::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 *==========================================================================*/ 80QCamera3PostProcessor::~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 *==========================================================================*/ 102int32_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 *==========================================================================*/ 129int32_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 *==========================================================================*/ 166int32_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 *==========================================================================*/ 213int32_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 *==========================================================================*/ 232int32_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 339on_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 *==========================================================================*/ 364int32_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 *==========================================================================*/ 413int32_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 *==========================================================================*/ 460int32_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 *==========================================================================*/ 485int32_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 *==========================================================================*/ 507int32_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 *==========================================================================*/ 553qcamera_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 *==========================================================================*/ 577void 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 *==========================================================================*/ 596void 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 *==========================================================================*/ 615void 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 *==========================================================================*/ 638void 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 *==========================================================================*/ 661void 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 *==========================================================================*/ 701mm_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 *==========================================================================*/ 731mm_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 *==========================================================================*/ 761int32_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_OFFLINE_PROC: 817 main_stream = srcStream; 818 main_frame = recvd_frame->bufs[i]; 819 break; 820 case CAM_STREAM_TYPE_PREVIEW: 821 case CAM_STREAM_TYPE_POSTVIEW: 822 thumb_stream = srcStream; 823 thumb_frame = recvd_frame->bufs[i]; 824 break; 825 default: 826 break; 827 } 828 } 829 } 830 831 if(NULL == main_frame){ 832 ALOGE("%s : Main frame is NULL", __func__); 833 return BAD_VALUE; 834 } 835 836 QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info; 837 if (NULL == memObj) { 838 ALOGE("%s : Memeory Obj of main frame is NULL", __func__); 839 return NO_MEMORY; 840 } 841 842 // clean and invalidate cache ops through mem obj of the frame 843 memObj->cleanInvalidateCache(main_frame->buf_idx); 844 845 if (thumb_frame != NULL) { 846 QCamera3Memory *thumb_memObj = (QCamera3Memory *)thumb_frame->mem_info; 847 if (NULL != thumb_memObj) { 848 // clean and invalidate cache ops through mem obj of the frame 849 thumb_memObj->cleanInvalidateCache(thumb_frame->buf_idx); 850 } 851 } 852 853 if (mJpegClientHandle <= 0) { 854 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__); 855 return UNKNOWN_ERROR; 856 } 857 858 ALOGD("%s: Need new session?:%d",__func__, needNewSess); 859 if (needNewSess) { 860 //creating a new session, so we must destroy the old one 861 if ( 0 < mJpegSessionId ) { 862 ret = mJpegHandle.destroy_session(mJpegSessionId); 863 if (ret != NO_ERROR) { 864 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d", 865 __func__, mJpegSessionId); 866 return ret; 867 } 868 mJpegSessionId = 0; 869 } 870 // create jpeg encoding session 871 mm_jpeg_encode_params_t encodeParam; 872 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t)); 873 874 getJpegEncodingConfig(encodeParam, main_stream, thumb_stream); 875 ALOGD("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__, 876 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs); 877 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId); 878 if (ret != NO_ERROR) { 879 ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret); 880 return ret; 881 } 882 needNewSess = FALSE; 883 } 884 885 // Fill in new job 886 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t)); 887 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE; 888 jpg_job.encode_job.session_id = mJpegSessionId; 889 jpg_job.encode_job.src_index = main_frame->buf_idx; 890 jpg_job.encode_job.dst_index = 0; 891 892 cam_rect_t crop; 893 memset(&crop, 0, sizeof(cam_rect_t)); 894 //TBD_later - Zoom event removed in stream 895 //main_stream->getCropInfo(crop); 896 897 cam_dimension_t src_dim; 898 memset(&src_dim, 0, sizeof(cam_dimension_t)); 899 main_stream->getFrameDimension(src_dim); 900 901 cam_dimension_t dst_dim; 902 memset(&dst_dim, 0, sizeof(cam_dimension_t)); 903 srcChannel->getStreamByIndex(0)->getFrameDimension(dst_dim); 904 905 // main dim 906 jpg_job.encode_job.main_dim.src_dim = src_dim; 907 jpg_job.encode_job.main_dim.dst_dim = dst_dim; 908 jpg_job.encode_job.main_dim.crop = crop; 909 910 // thumbnail dim 911 ALOGD("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded); 912 if (m_bThumbnailNeeded == TRUE) { 913 if (thumb_stream == NULL) { 914 // need jpeg thumbnail, but no postview/preview stream exists 915 // we use the main stream/frame to encode thumbnail 916 thumb_stream = main_stream; 917 thumb_frame = main_frame; 918 } 919 memset(&crop, 0, sizeof(cam_rect_t)); 920 //TBD_later - Zoom event removed in stream 921 //thumb_stream->getCropInfo(crop); 922 memset(&src_dim, 0, sizeof(cam_dimension_t)); 923 thumb_stream->getFrameDimension(src_dim); 924 jpg_job.encode_job.thumb_dim.src_dim = src_dim; 925 m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim); 926 jpg_job.encode_job.thumb_dim.crop = crop; 927 jpg_job.encode_job.thumb_index = thumb_frame->buf_idx; 928 } 929 if (!hal_obj->needRotationReprocess()) { 930 jpg_job.encode_job.rotation = m_parent->getJpegRotation(); 931 ALOGD("%s: jpeg rotation is set to %d", __func__, jpg_job.encode_job.rotation); 932 } 933 934 // Find meta data frame. Meta data frame contains additional exif info 935 // which will be extracted and filled in by encoder. 936 //Note: In this version meta data will be null 937 //as we don't support bundling of snapshot and metadata streams. 938 939 mm_camera_buf_def_t *meta_frame = NULL; 940 if(jpeg_job_data->src_frame) { 941 for (int i = 0; i < jpeg_job_data->src_frame->num_bufs; i++) { 942 // look through input superbuf 943 if (jpeg_job_data->src_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 944 meta_frame = jpeg_job_data->src_frame->bufs[i]; 945 break; 946 } 947 } 948 } 949 if (meta_frame == NULL && jpeg_job_data->src_reproc_frame != NULL) { 950 // look through reprocess source superbuf 951 for (int i = 0; i < jpeg_job_data->src_reproc_frame->num_bufs; i++) { 952 if (jpeg_job_data->src_reproc_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 953 meta_frame = jpeg_job_data->src_reproc_frame->bufs[i]; 954 break; 955 } 956 } 957 } 958 if (meta_frame != NULL) { 959 // fill in meta data frame ptr 960 jpg_job.encode_job.p_metadata = (cam_metadata_info_t *)meta_frame->buffer; 961 } 962 963 //Start jpeg encoding 964 ret = mJpegHandle.start_job(&jpg_job, &jobId); 965 if (ret == NO_ERROR) { 966 // remember job info 967 jpeg_job_data->jobId = jobId; 968 } 969 970 ALOGV("%s : X", __func__); 971 return ret; 972} 973 974/*=========================================================================== 975 * FUNCTION : dataProcessRoutine 976 * 977 * DESCRIPTION: data process routine that handles input data either from input 978 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do 979 * reprocess. 980 * 981 * PARAMETERS : 982 * @data : user data ptr (QCamera3PostProcessor) 983 * 984 * RETURN : None 985 *==========================================================================*/ 986void *QCamera3PostProcessor::dataProcessRoutine(void *data) 987{ 988 int running = 1; 989 int ret; 990 uint8_t is_active = FALSE; 991 uint8_t needNewSess = TRUE; 992 ALOGV("%s: E", __func__); 993 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data; 994 QCameraCmdThread *cmdThread = &pme->m_dataProcTh; 995 996 do { 997 do { 998 ret = cam_sem_wait(&cmdThread->cmd_sem); 999 if (ret != 0 && errno != EINVAL) { 1000 ALOGE("%s: cam_sem_wait error (%s)", 1001 __func__, strerror(errno)); 1002 return NULL; 1003 } 1004 } while (ret != 0); 1005 1006 // we got notified about new cmd avail in cmd queue 1007 camera_cmd_type_t cmd = cmdThread->getCmd(); 1008 switch (cmd) { 1009 case CAMERA_CMD_TYPE_START_DATA_PROC: 1010 ALOGD("%s: start data proc", __func__); 1011 is_active = TRUE; 1012 needNewSess = TRUE; 1013 break; 1014 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 1015 { 1016 ALOGD("%s: stop data proc", __func__); 1017 is_active = FALSE; 1018 1019 // cancel all ongoing jpeg jobs 1020 qcamera_jpeg_data_t *jpeg_job = 1021 (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1022 while (jpeg_job != NULL) { 1023 pme->mJpegHandle.abort_job(jpeg_job->jobId); 1024 1025 pme->releaseJpegJobData(jpeg_job); 1026 free(jpeg_job); 1027 1028 jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1029 } 1030 1031 // destroy jpeg encoding session 1032 if ( 0 < pme->mJpegSessionId ) { 1033 pme->mJpegHandle.destroy_session(pme->mJpegSessionId); 1034 pme->mJpegSessionId = 0; 1035 } 1036 1037 // free jpeg exif obj 1038 if (pme->m_pJpegExifObj != NULL) { 1039 delete pme->m_pJpegExifObj; 1040 pme->m_pJpegExifObj = NULL; 1041 } 1042 needNewSess = TRUE; 1043 1044 // flush ongoing postproc Queue 1045 pme->m_ongoingPPQ.flush(); 1046 1047 // flush input jpeg Queue 1048 pme->m_inputJpegQ.flush(); 1049 1050 // flush input Postproc Queue 1051 pme->m_inputPPQ.flush(); 1052 1053 // flush input raw Queue 1054 pme->m_inputRawQ.flush(); 1055 1056 pme->m_inputMetaQ.flush(); 1057 1058 // signal cmd is completed 1059 cam_sem_post(&cmdThread->sync_sem); 1060 } 1061 break; 1062 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 1063 { 1064 ALOGD("%s: Do next job, active is %d", __func__, is_active); 1065 if (is_active == TRUE) { 1066 // check if there is any ongoing jpeg jobs 1067 if (pme->m_ongoingJpegQ.isEmpty()) { 1068 // no ongoing jpeg job, we are fine to send jpeg encoding job 1069 qcamera_jpeg_data_t *jpeg_job = 1070 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 1071 1072 if (NULL != jpeg_job) { 1073 //TBD_later - play shutter sound 1074 //pme->m_parent->playShutter(); 1075 1076 // add into ongoing jpeg job Q 1077 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job); 1078 ret = pme->encodeData(jpeg_job, needNewSess); 1079 if (NO_ERROR != ret) { 1080 // dequeue the last one 1081 pme->m_ongoingJpegQ.dequeue(false); 1082 1083 pme->releaseJpegJobData(jpeg_job); 1084 free(jpeg_job); 1085 } 1086 } 1087 } 1088 1089 mm_camera_super_buf_t *pp_frame = 1090 (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 1091 if (NULL != pp_frame) { 1092 mm_camera_super_buf_t *meta_frame = NULL; 1093 meta_frame = 1094 (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue(); 1095 if (meta_frame == NULL) { 1096 ALOGE("%s: did not get a corresponding metadata", __func__); 1097 } 1098 // meta_frame != NULL 1099 qcamera_pp_data_t *pp_job = 1100 (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t)); 1101 if (pp_job != NULL) { 1102 memset(pp_job, 0, sizeof(qcamera_pp_data_t)); 1103 if (pme->m_pReprocChannel != NULL) { 1104 // add into ongoing PP job Q 1105 pp_job->src_frame = pp_frame; 1106 pme->m_ongoingPPQ.enqueue((void *)pp_job); 1107 ret = pme->m_pReprocChannel->doReprocess(pp_frame, meta_frame); 1108 if (NO_ERROR != ret) { 1109 // remove from ongoing PP job Q 1110 pme->m_ongoingPPQ.dequeue(false); 1111 } 1112 } else { 1113 ALOGE("%s: Reprocess channel is NULL", __func__); 1114 ret = -1; 1115 } 1116 } else { 1117 ALOGE("%s: no mem for qcamera_pp_data_t", __func__); 1118 ret = -1; 1119 } 1120 1121 if (0 != ret) { 1122 // free pp_job 1123 if (pp_job != NULL) { 1124 free(pp_job); 1125 } 1126 // free frame 1127 if (pp_frame != NULL) { 1128 pme->releaseSuperBuf(pp_frame); 1129 free(pp_frame); 1130 } 1131 } 1132 } 1133 } else { 1134 // not active, simply return buf and do no op 1135 mm_camera_super_buf_t *super_buf = 1136 (mm_camera_super_buf_t *)pme->m_inputJpegQ.dequeue(); 1137 if (NULL != super_buf) { 1138 pme->releaseSuperBuf(super_buf); 1139 free(super_buf); 1140 } 1141 super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 1142 if (NULL != super_buf) { 1143 pme->releaseSuperBuf(super_buf); 1144 free(super_buf); 1145 } 1146 super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 1147 if (NULL != super_buf) { 1148 pme->releaseSuperBuf(super_buf); 1149 free(super_buf); 1150 } 1151 super_buf = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue(); 1152 if (NULL != super_buf) { 1153 pme->releaseSuperBuf(super_buf); 1154 free(super_buf); 1155 } 1156 } 1157 } 1158 break; 1159 case CAMERA_CMD_TYPE_EXIT: 1160 running = 0; 1161 break; 1162 default: 1163 break; 1164 } 1165 } while (running); 1166 ALOGV("%s: X", __func__); 1167 return NULL; 1168} 1169 1170/*=========================================================================== 1171 * FUNCTION : QCamera3Exif 1172 * 1173 * DESCRIPTION: constructor of QCamera3Exif 1174 * 1175 * PARAMETERS : None 1176 * 1177 * RETURN : None 1178 *==========================================================================*/ 1179QCamera3Exif::QCamera3Exif() 1180 : m_nNumEntries(0) 1181{ 1182 memset(m_Entries, 0, sizeof(m_Entries)); 1183} 1184 1185/*=========================================================================== 1186 * FUNCTION : ~QCamera3Exif 1187 * 1188 * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr. 1189 * 1190 * PARAMETERS : None 1191 * 1192 * RETURN : None 1193 *==========================================================================*/ 1194QCamera3Exif::~QCamera3Exif() 1195{ 1196 for (uint32_t i = 0; i < m_nNumEntries; i++) { 1197 switch (m_Entries[i].tag_entry.type) { 1198 case EXIF_BYTE: 1199 { 1200 if (m_Entries[i].tag_entry.count > 1 && 1201 m_Entries[i].tag_entry.data._bytes != NULL) { 1202 free(m_Entries[i].tag_entry.data._bytes); 1203 m_Entries[i].tag_entry.data._bytes = NULL; 1204 } 1205 } 1206 break; 1207 case EXIF_ASCII: 1208 { 1209 if (m_Entries[i].tag_entry.data._ascii != NULL) { 1210 free(m_Entries[i].tag_entry.data._ascii); 1211 m_Entries[i].tag_entry.data._ascii = NULL; 1212 } 1213 } 1214 break; 1215 case EXIF_SHORT: 1216 { 1217 if (m_Entries[i].tag_entry.count > 1 && 1218 m_Entries[i].tag_entry.data._shorts != NULL) { 1219 free(m_Entries[i].tag_entry.data._shorts); 1220 m_Entries[i].tag_entry.data._shorts = NULL; 1221 } 1222 } 1223 break; 1224 case EXIF_LONG: 1225 { 1226 if (m_Entries[i].tag_entry.count > 1 && 1227 m_Entries[i].tag_entry.data._longs != NULL) { 1228 free(m_Entries[i].tag_entry.data._longs); 1229 m_Entries[i].tag_entry.data._longs = NULL; 1230 } 1231 } 1232 break; 1233 case EXIF_RATIONAL: 1234 { 1235 if (m_Entries[i].tag_entry.count > 1 && 1236 m_Entries[i].tag_entry.data._rats != NULL) { 1237 free(m_Entries[i].tag_entry.data._rats); 1238 m_Entries[i].tag_entry.data._rats = NULL; 1239 } 1240 } 1241 break; 1242 case EXIF_UNDEFINED: 1243 { 1244 if (m_Entries[i].tag_entry.data._undefined != NULL) { 1245 free(m_Entries[i].tag_entry.data._undefined); 1246 m_Entries[i].tag_entry.data._undefined = NULL; 1247 } 1248 } 1249 break; 1250 case EXIF_SLONG: 1251 { 1252 if (m_Entries[i].tag_entry.count > 1 && 1253 m_Entries[i].tag_entry.data._slongs != NULL) { 1254 free(m_Entries[i].tag_entry.data._slongs); 1255 m_Entries[i].tag_entry.data._slongs = NULL; 1256 } 1257 } 1258 break; 1259 case EXIF_SRATIONAL: 1260 { 1261 if (m_Entries[i].tag_entry.count > 1 && 1262 m_Entries[i].tag_entry.data._srats != NULL) { 1263 free(m_Entries[i].tag_entry.data._srats); 1264 m_Entries[i].tag_entry.data._srats = NULL; 1265 } 1266 } 1267 break; 1268 default: 1269 ALOGE("%s: Error, Unknown type",__func__); 1270 break; 1271 } 1272 } 1273} 1274 1275/*=========================================================================== 1276 * FUNCTION : addEntry 1277 * 1278 * DESCRIPTION: function to add an entry to exif data 1279 * 1280 * PARAMETERS : 1281 * @tagid : exif tag ID 1282 * @type : data type 1283 * @count : number of data in uint of its type 1284 * @data : input data ptr 1285 * 1286 * RETURN : int32_t type of status 1287 * NO_ERROR -- success 1288 * none-zero failure code 1289 *==========================================================================*/ 1290int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid, 1291 exif_tag_type_t type, 1292 uint32_t count, 1293 void *data) 1294{ 1295 int32_t rc = NO_ERROR; 1296 if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) { 1297 ALOGE("%s: Number of entries exceeded limit", __func__); 1298 return NO_MEMORY; 1299 } 1300 1301 m_Entries[m_nNumEntries].tag_id = tagid; 1302 m_Entries[m_nNumEntries].tag_entry.type = type; 1303 m_Entries[m_nNumEntries].tag_entry.count = count; 1304 m_Entries[m_nNumEntries].tag_entry.copy = 1; 1305 switch (type) { 1306 case EXIF_BYTE: 1307 { 1308 if (count > 1) { 1309 uint8_t *values = (uint8_t *)malloc(count); 1310 if (values == NULL) { 1311 ALOGE("%s: No memory for byte array", __func__); 1312 rc = NO_MEMORY; 1313 } else { 1314 memcpy(values, data, count); 1315 m_Entries[m_nNumEntries].tag_entry.data._bytes = values; 1316 } 1317 } else { 1318 m_Entries[m_nNumEntries].tag_entry.data._byte = 1319 *(uint8_t *)data; 1320 } 1321 } 1322 break; 1323 case EXIF_ASCII: 1324 { 1325 char *str = NULL; 1326 str = (char *)malloc(count + 1); 1327 if (str == NULL) { 1328 ALOGE("%s: No memory for ascii string", __func__); 1329 rc = NO_MEMORY; 1330 } else { 1331 memset(str, 0, count + 1); 1332 memcpy(str, data, count); 1333 m_Entries[m_nNumEntries].tag_entry.data._ascii = str; 1334 } 1335 } 1336 break; 1337 case EXIF_SHORT: 1338 { 1339 if (count > 1) { 1340 uint16_t *values = 1341 (uint16_t *)malloc(count * sizeof(uint16_t)); 1342 if (values == NULL) { 1343 ALOGE("%s: No memory for short array", __func__); 1344 rc = NO_MEMORY; 1345 } else { 1346 memcpy(values, data, count * sizeof(uint16_t)); 1347 m_Entries[m_nNumEntries].tag_entry.data._shorts =values; 1348 } 1349 } else { 1350 m_Entries[m_nNumEntries].tag_entry.data._short = 1351 *(uint16_t *)data; 1352 } 1353 } 1354 break; 1355 case EXIF_LONG: 1356 { 1357 if (count > 1) { 1358 uint32_t *values = 1359 (uint32_t *)malloc(count * sizeof(uint32_t)); 1360 if (values == NULL) { 1361 ALOGE("%s: No memory for long array", __func__); 1362 rc = NO_MEMORY; 1363 } else { 1364 memcpy(values, data, count * sizeof(uint32_t)); 1365 m_Entries[m_nNumEntries].tag_entry.data._longs = values; 1366 } 1367 } else { 1368 m_Entries[m_nNumEntries].tag_entry.data._long = 1369 *(uint32_t *)data; 1370 } 1371 } 1372 break; 1373 case EXIF_RATIONAL: 1374 { 1375 if (count > 1) { 1376 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t)); 1377 if (values == NULL) { 1378 ALOGE("%s: No memory for rational array", __func__); 1379 rc = NO_MEMORY; 1380 } else { 1381 memcpy(values, data, count * sizeof(rat_t)); 1382 m_Entries[m_nNumEntries].tag_entry.data._rats = values; 1383 } 1384 } else { 1385 m_Entries[m_nNumEntries].tag_entry.data._rat = 1386 *(rat_t *)data; 1387 } 1388 } 1389 break; 1390 case EXIF_UNDEFINED: 1391 { 1392 uint8_t *values = (uint8_t *)malloc(count); 1393 if (values == NULL) { 1394 ALOGE("%s: No memory for undefined array", __func__); 1395 rc = NO_MEMORY; 1396 } else { 1397 memcpy(values, data, count); 1398 m_Entries[m_nNumEntries].tag_entry.data._undefined = values; 1399 } 1400 } 1401 break; 1402 case EXIF_SLONG: 1403 { 1404 if (count > 1) { 1405 int32_t *values = 1406 (int32_t *)malloc(count * sizeof(int32_t)); 1407 if (values == NULL) { 1408 ALOGE("%s: No memory for signed long array", __func__); 1409 rc = NO_MEMORY; 1410 } else { 1411 memcpy(values, data, count * sizeof(int32_t)); 1412 m_Entries[m_nNumEntries].tag_entry.data._slongs =values; 1413 } 1414 } else { 1415 m_Entries[m_nNumEntries].tag_entry.data._slong = 1416 *(int32_t *)data; 1417 } 1418 } 1419 break; 1420 case EXIF_SRATIONAL: 1421 { 1422 if (count > 1) { 1423 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t)); 1424 if (values == NULL) { 1425 ALOGE("%s: No memory for sign rational array",__func__); 1426 rc = NO_MEMORY; 1427 } else { 1428 memcpy(values, data, count * sizeof(srat_t)); 1429 m_Entries[m_nNumEntries].tag_entry.data._srats = values; 1430 } 1431 } else { 1432 m_Entries[m_nNumEntries].tag_entry.data._srat = 1433 *(srat_t *)data; 1434 } 1435 } 1436 break; 1437 default: 1438 ALOGE("%s: Error, Unknown type",__func__); 1439 break; 1440 } 1441 1442 // Increase number of entries 1443 m_nNumEntries++; 1444 return rc; 1445} 1446 1447}; // namespace qcamera 1448