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