1 /* Copyright (c) 2012-2015, 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 #define ATRACE_TAG ATRACE_TAG_CAMERA 30 31 #define LOG_TAG "QCamera3PostProc" 32 //#define LOG_NDEBUG 0 33 34 #include <stdlib.h> 35 #include <utils/Errors.h> 36 #include <utils/Trace.h> 37 38 #include "QCamera3PostProc.h" 39 #include "QCamera3HWI.h" 40 #include "QCamera3Channel.h" 41 #include "QCamera3Stream.h" 42 43 namespace qcamera { 44 45 /*=========================================================================== 46 * FUNCTION : QCamera3PostProcessor 47 * 48 * DESCRIPTION: constructor of QCamera3PostProcessor. 49 * 50 * PARAMETERS : 51 * @cam_ctrl : ptr to HWI object 52 * 53 * RETURN : None 54 *==========================================================================*/ 55 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3PicChannel* ch_ctrl) 56 : m_parent(ch_ctrl), 57 mJpegCB(NULL), 58 mJpegUserData(NULL), 59 mJpegClientHandle(0), 60 mJpegSessionId(0), 61 m_bThumbnailNeeded(TRUE), 62 m_pReprocChannel(NULL), 63 m_inputPPQ(releasePPInputData, this), 64 m_inputFWKPPQ(NULL, this), 65 m_ongoingPPQ(releaseOngoingPPData, this), 66 m_inputJpegQ(releaseJpegData, this), 67 m_ongoingJpegQ(releaseJpegData, this), 68 m_inputRawQ(releasePPInputData, this), 69 m_inputMetaQ(releaseMetadata, this), 70 m_jpegSettingsQ(NULL, this) 71 { 72 memset(&mJpegHandle, 0, sizeof(mJpegHandle)); 73 pthread_mutex_init(&mReprocJobLock, NULL); 74 } 75 76 /*=========================================================================== 77 * FUNCTION : ~QCamera3PostProcessor 78 * 79 * DESCRIPTION: deconstructor of QCamera3PostProcessor. 80 * 81 * PARAMETERS : None 82 * 83 * RETURN : None 84 *==========================================================================*/ 85 QCamera3PostProcessor::~QCamera3PostProcessor() 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(QCamera3Memory* mMemory, 104 jpeg_encode_callback_t jpeg_cb, 105 uint32_t postprocess_mask, 106 void *user_data) 107 { 108 ATRACE_CALL(); 109 mJpegCB = jpeg_cb; 110 mJpegUserData = user_data; 111 mm_dimension max_size; 112 113 //set max pic size 114 memset(&max_size, 0, sizeof(mm_dimension)); 115 max_size.w = m_parent->m_max_pic_dim.width; 116 max_size.h = m_parent->m_max_pic_dim.height; 117 118 mJpegClientHandle = jpeg_open(&mJpegHandle,max_size); 119 mJpegMem = mMemory; 120 if(!mJpegClientHandle) { 121 ALOGE("%s : jpeg_open did not work", __func__); 122 return UNKNOWN_ERROR; 123 } 124 mPostProcMask = postprocess_mask; 125 m_dataProcTh.launch(dataProcessRoutine, this); 126 127 return NO_ERROR; 128 } 129 130 /*=========================================================================== 131 * FUNCTION : deinit 132 * 133 * DESCRIPTION: de-initialization of postprocessor 134 * 135 * PARAMETERS : None 136 * 137 * RETURN : int32_t type of status 138 * NO_ERROR -- success 139 * none-zero failure code 140 *==========================================================================*/ 141 int32_t QCamera3PostProcessor::deinit() 142 { 143 m_dataProcTh.exit(); 144 145 if (m_pReprocChannel != NULL) { 146 m_pReprocChannel->stop(); 147 delete m_pReprocChannel; 148 m_pReprocChannel = NULL; 149 } 150 151 if(mJpegClientHandle > 0) { 152 int rc = mJpegHandle.close(mJpegClientHandle); 153 CDBG_HIGH("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x", 154 __func__, rc, mJpegClientHandle); 155 mJpegClientHandle = 0; 156 memset(&mJpegHandle, 0, sizeof(mJpegHandle)); 157 } 158 159 mJpegMem = NULL; 160 161 return NO_ERROR; 162 } 163 164 /*=========================================================================== 165 * FUNCTION : start 166 * 167 * DESCRIPTION: start postprocessor. Data process thread and data notify thread 168 * will be launched. 169 * 170 * PARAMETERS : 171 * @pMemory : memory object representing buffers to store JPEG. 172 * @config : reprocess configuration 173 * @metadata : metadata for the reprocessing 174 * 175 * RETURN : int32_t type of status 176 * NO_ERROR -- success 177 * none-zero failure code 178 * 179 * NOTE : if any reprocess is needed, a reprocess channel/stream 180 * will be started. 181 *==========================================================================*/ 182 int32_t QCamera3PostProcessor::start(const reprocess_config_t &config, 183 metadata_buffer_t *metadata) 184 { 185 int32_t rc = NO_ERROR; 186 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData; 187 188 if (hal_obj->needReprocess(mPostProcMask) || config.src_channel != m_parent) { 189 if (m_pReprocChannel != NULL) { 190 m_pReprocChannel->stop(); 191 delete m_pReprocChannel; 192 m_pReprocChannel = NULL; 193 } 194 195 // if reprocess is needed, start reprocess channel 196 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData; 197 CDBG("%s: Setting input channel as pInputChannel", __func__); 198 m_pReprocChannel = hal_obj->addOfflineReprocChannel(config, m_parent, metadata); 199 if (m_pReprocChannel == NULL) { 200 ALOGE("%s: cannot add reprocess channel", __func__); 201 return UNKNOWN_ERROR; 202 } 203 204 rc = m_pReprocChannel->start(); 205 if (rc != 0) { 206 ALOGE("%s: cannot start reprocess channel", __func__); 207 delete m_pReprocChannel; 208 m_pReprocChannel = NULL; 209 return rc; 210 } 211 } 212 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, TRUE, FALSE); 213 214 return rc; 215 } 216 217 /*=========================================================================== 218 * FUNCTION : stop 219 * 220 * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped. 221 * 222 * PARAMETERS : None 223 * 224 * RETURN : int32_t type of status 225 * NO_ERROR -- success 226 * none-zero failure code 227 * 228 * NOTE : reprocess channel will be stopped and deleted if there is any 229 *==========================================================================*/ 230 int32_t QCamera3PostProcessor::stop() 231 { 232 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE); 233 234 if (m_pReprocChannel != NULL) { 235 m_pReprocChannel->stop(); 236 delete m_pReprocChannel; 237 m_pReprocChannel = NULL; 238 } 239 240 return NO_ERROR; 241 } 242 243 /*=========================================================================== 244 * FUNCTION : getFWKJpegEncodeConfig 245 * 246 * DESCRIPTION: function to prepare encoding job information 247 * 248 * PARAMETERS : 249 * @encode_parm : param to be filled with encoding configuration 250 * @frame : framework input buffer 251 * @jpeg_settings : jpeg settings to be applied for encoding 252 * 253 * RETURN : int32_t type of status 254 * NO_ERROR -- success 255 * none-zero failure code 256 *==========================================================================*/ 257 int32_t QCamera3PostProcessor::getFWKJpegEncodeConfig( 258 mm_jpeg_encode_params_t& encode_parm, 259 qcamera_fwk_input_pp_data_t *frame, 260 jpeg_settings_t *jpeg_settings) 261 { 262 CDBG("%s : E", __func__); 263 264 if ((NULL == frame) || (NULL == jpeg_settings)) { 265 return BAD_VALUE; 266 } 267 268 encode_parm.jpeg_cb = mJpegCB; 269 encode_parm.userdata = mJpegUserData; 270 271 if (jpeg_settings->thumbnail_size.width > 0 && 272 jpeg_settings->thumbnail_size.height > 0) 273 m_bThumbnailNeeded = TRUE; 274 else 275 m_bThumbnailNeeded = FALSE; 276 encode_parm.encode_thumbnail = m_bThumbnailNeeded; 277 278 // get color format 279 cam_format_t img_fmt = frame->reproc_config.stream_format; 280 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt); 281 282 // get jpeg quality 283 encode_parm.quality = jpeg_settings->jpeg_quality; 284 if (encode_parm.quality <= 0) { 285 encode_parm.quality = 85; 286 } 287 288 // get jpeg thumbnail quality 289 encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality; 290 291 cam_frame_len_offset_t main_offset = 292 frame->reproc_config.input_stream_plane_info.plane_info; 293 294 encode_parm.num_src_bufs = 1; 295 encode_parm.src_main_buf[0].index = 0; 296 encode_parm.src_main_buf[0].buf_size = frame->input_buffer.frame_len; 297 encode_parm.src_main_buf[0].buf_vaddr = (uint8_t *) frame->input_buffer.buffer; 298 encode_parm.src_main_buf[0].fd = frame->input_buffer.fd; 299 encode_parm.src_main_buf[0].format = MM_JPEG_FMT_YUV; 300 encode_parm.src_main_buf[0].offset = main_offset; 301 302 //Pass input thumbnail buffer info to encoder. 303 //Note: Use main buffer to encode thumbnail 304 if (m_bThumbnailNeeded == TRUE) { 305 encode_parm.num_tmb_bufs = 1; 306 encode_parm.src_thumb_buf[0] = encode_parm.src_main_buf[0]; 307 } 308 309 //Pass output jpeg buffer info to encoder. 310 //mJpegMem is allocated by framework. 311 encode_parm.num_dst_bufs = 1; 312 encode_parm.dest_buf[0].index = 0; 313 encode_parm.dest_buf[0].buf_size = mJpegMem->getSize( 314 jpeg_settings->out_buf_index); 315 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr( 316 jpeg_settings->out_buf_index); 317 encode_parm.dest_buf[0].fd = mJpegMem->getFd( 318 jpeg_settings->out_buf_index); 319 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV; 320 encode_parm.dest_buf[0].offset = main_offset; 321 322 CDBG("%s : X", __func__); 323 return NO_ERROR; 324 } 325 326 /*=========================================================================== 327 * FUNCTION : getJpegEncodeConfig 328 * 329 * DESCRIPTION: function to prepare encoding job information 330 * 331 * PARAMETERS : 332 * @encode_parm : param to be filled with encoding configuration 333 * #main_stream : stream object where the input buffer comes from 334 * @jpeg_settings : jpeg settings to be applied for encoding 335 * 336 * RETURN : int32_t type of status 337 * NO_ERROR -- success 338 * none-zero failure code 339 *==========================================================================*/ 340 int32_t QCamera3PostProcessor::getJpegEncodeConfig( 341 mm_jpeg_encode_params_t& encode_parm, 342 QCamera3Stream *main_stream, 343 jpeg_settings_t *jpeg_settings) 344 { 345 CDBG("%s : E", __func__); 346 int32_t ret = NO_ERROR; 347 348 encode_parm.jpeg_cb = mJpegCB; 349 encode_parm.userdata = mJpegUserData; 350 351 if (jpeg_settings->thumbnail_size.width > 0 && 352 jpeg_settings->thumbnail_size.height > 0) 353 m_bThumbnailNeeded = TRUE; 354 else 355 m_bThumbnailNeeded = FALSE; 356 encode_parm.encode_thumbnail = m_bThumbnailNeeded; 357 358 // get color format 359 cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12; //default value 360 main_stream->getFormat(img_fmt); 361 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt); 362 363 //get rotation 364 encode_parm.jpeg_orientation = jpeg_settings->jpeg_orientation; 365 366 // get jpeg quality 367 encode_parm.quality = jpeg_settings->jpeg_quality; 368 if (encode_parm.quality <= 0) { 369 encode_parm.quality = 85; 370 } 371 372 // get jpeg thumbnail quality 373 encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality; 374 375 cam_frame_len_offset_t main_offset; 376 memset(&main_offset, 0, sizeof(cam_frame_len_offset_t)); 377 main_stream->getFrameOffset(main_offset); 378 379 // src buf config 380 //Pass input main image buffer info to encoder. 381 QCamera3Memory *pStreamMem = main_stream->getStreamBufs(); 382 if (pStreamMem == NULL) { 383 ALOGE("%s: cannot get stream bufs from main stream", __func__); 384 ret = BAD_VALUE; 385 goto on_error; 386 } 387 encode_parm.num_src_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF); 388 for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) { 389 if (pStreamMem != NULL) { 390 encode_parm.src_main_buf[i].index = i; 391 encode_parm.src_main_buf[i].buf_size = pStreamMem->getSize(i); 392 encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i); 393 encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i); 394 encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV; 395 encode_parm.src_main_buf[i].offset = main_offset; 396 } 397 } 398 399 //Pass input thumbnail buffer info to encoder. 400 //Note: Use main buffer to encode thumbnail 401 if (m_bThumbnailNeeded == TRUE) { 402 pStreamMem = main_stream->getStreamBufs(); 403 if (pStreamMem == NULL) { 404 ALOGE("%s: cannot get stream bufs from thumb stream", __func__); 405 ret = BAD_VALUE; 406 goto on_error; 407 } 408 cam_frame_len_offset_t thumb_offset; 409 memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t)); 410 main_stream->getFrameOffset(thumb_offset); 411 encode_parm.num_tmb_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF); 412 for (size_t i = 0; i < encode_parm.num_tmb_bufs; i++) { 413 if (pStreamMem != NULL) { 414 encode_parm.src_thumb_buf[i].index = i; 415 encode_parm.src_thumb_buf[i].buf_size = pStreamMem->getSize(i); 416 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i); 417 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i); 418 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV; 419 encode_parm.src_thumb_buf[i].offset = thumb_offset; 420 } 421 } 422 } 423 424 //Pass output jpeg buffer info to encoder. 425 //mJpegMem is allocated by framework. 426 encode_parm.num_dst_bufs = 1; 427 encode_parm.dest_buf[0].index = 0; 428 encode_parm.dest_buf[0].buf_size = mJpegMem->getSize( 429 jpeg_settings->out_buf_index); 430 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr( 431 jpeg_settings->out_buf_index); 432 encode_parm.dest_buf[0].fd = mJpegMem->getFd( 433 jpeg_settings->out_buf_index); 434 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV; 435 encode_parm.dest_buf[0].offset = main_offset; 436 437 CDBG("%s : X", __func__); 438 return NO_ERROR; 439 440 on_error: 441 CDBG("%s : X with error %d", __func__, ret); 442 return ret; 443 } 444 445 /*=========================================================================== 446 * FUNCTION : processData 447 * 448 * DESCRIPTION: enqueue data into dataProc thread 449 * 450 * PARAMETERS : 451 * @frame : process frame 452 * 453 * RETURN : int32_t type of status 454 * NO_ERROR -- success 455 * none-zero failure code 456 * 457 * NOTE : depends on if offline reprocess is needed, received frame will 458 * be sent to either input queue of postprocess or jpeg encoding 459 *==========================================================================*/ 460 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame) 461 { 462 pthread_mutex_lock(&mReprocJobLock); 463 // enqueue to post proc input queue 464 m_inputPPQ.enqueue((void *)frame); 465 if (!(m_inputMetaQ.isEmpty())) { 466 CDBG("%s: meta 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 471 return NO_ERROR; 472 } 473 474 /*=========================================================================== 475 * FUNCTION : processData 476 * 477 * DESCRIPTION: enqueue data into dataProc thread 478 * 479 * PARAMETERS : 480 * @frame : process frame 481 * 482 * RETURN : int32_t type of status 483 * NO_ERROR -- success 484 * none-zero failure code 485 * 486 * NOTE : depends on if offline reprocess is needed, received frame will 487 * be sent to either input queue of postprocess or jpeg encoding 488 *==========================================================================*/ 489 int32_t QCamera3PostProcessor::processData(qcamera_fwk_input_pp_data_t *frame) 490 { 491 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData; 492 if (hal_obj->needReprocess(mPostProcMask) || 493 frame->reproc_config.src_channel != m_parent) { 494 pthread_mutex_lock(&mReprocJobLock); 495 // enqueu to post proc input queue 496 m_inputFWKPPQ.enqueue((void *)frame); 497 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 498 pthread_mutex_unlock(&mReprocJobLock); 499 } else { 500 jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue(); 501 502 if (jpeg_settings == NULL) { 503 ALOGE("%s: Cannot find jpeg settings", __func__); 504 return BAD_VALUE; 505 } 506 507 CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__); 508 qcamera_hal3_jpeg_data_t *jpeg_job = 509 (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t)); 510 if (jpeg_job == NULL) { 511 ALOGE("%s: No memory for jpeg job", __func__); 512 return NO_MEMORY; 513 } 514 515 memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t)); 516 jpeg_job->fwk_frame = frame; 517 jpeg_job->jpeg_settings = jpeg_settings; 518 jpeg_job->metadata = 519 (metadata_buffer_t *) frame->metadata_buffer.buffer; 520 521 // enqueu to jpeg input queue 522 m_inputJpegQ.enqueue((void *)jpeg_job); 523 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 524 } 525 526 return NO_ERROR; 527 } 528 529 /*=========================================================================== 530 * FUNCTION : processPPMetadata 531 * 532 * DESCRIPTION: enqueue data into dataProc thread 533 * 534 * PARAMETERS : 535 * @frame : process metadata frame received from pic channel 536 * 537 * RETURN : int32_t type of status 538 * NO_ERROR -- success 539 * none-zero failure code 540 * 541 *==========================================================================*/ 542 int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta) 543 { 544 pthread_mutex_lock(&mReprocJobLock); 545 // enqueue to metadata input queue 546 m_inputMetaQ.enqueue((void *)reproc_meta); 547 if (!(m_inputPPQ.isEmpty())) { 548 CDBG("%s: pp queue is not empty, do next job", __func__); 549 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 550 } else { 551 CDBG("%s: pp queue is empty, not calling do next job", __func__); 552 } 553 pthread_mutex_unlock(&mReprocJobLock); 554 return NO_ERROR; 555 } 556 557 /*=========================================================================== 558 * FUNCTION : processJpegSettingData 559 * 560 * DESCRIPTION: enqueue jpegSetting into dataProc thread 561 * 562 * PARAMETERS : 563 * @jpeg_settings : jpeg settings data received from pic channel 564 * 565 * RETURN : int32_t type of status 566 * NO_ERROR -- success 567 * none-zero failure code 568 * 569 *==========================================================================*/ 570 int32_t QCamera3PostProcessor::processJpegSettingData( 571 jpeg_settings_t *jpeg_settings) 572 { 573 if (!jpeg_settings) { 574 ALOGE("%s: invalid jpeg settings pointer", __func__); 575 return -EINVAL; 576 } 577 return m_jpegSettingsQ.enqueue((void *)jpeg_settings); 578 } 579 580 /*=========================================================================== 581 * FUNCTION : processRawData 582 * 583 * DESCRIPTION: enqueue raw data into dataProc thread 584 * 585 * PARAMETERS : 586 * @frame : process frame received from mm-camera-interface 587 * 588 * RETURN : int32_t type of status 589 * NO_ERROR -- success 590 * none-zero failure code 591 *==========================================================================*/ 592 int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame) 593 { 594 // enqueu to raw input queue 595 m_inputRawQ.enqueue((void *)frame); 596 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 597 return NO_ERROR; 598 } 599 600 /*=========================================================================== 601 * FUNCTION : processPPData 602 * 603 * DESCRIPTION: process received frame after reprocess. 604 * 605 * PARAMETERS : 606 * @frame : received frame from reprocess channel. 607 * 608 * RETURN : int32_t type of status 609 * NO_ERROR -- success 610 * none-zero failure code 611 * 612 * NOTE : The frame after reprocess need to send to jpeg encoding. 613 *==========================================================================*/ 614 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame) 615 { 616 qcamera_hal3_pp_data_t *job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue(); 617 618 if (job == NULL || ((NULL == job->src_frame) && (NULL == job->fwk_src_frame))) { 619 ALOGE("%s: Cannot find reprocess job", __func__); 620 return BAD_VALUE; 621 } 622 if (job->jpeg_settings == NULL) { 623 ALOGE("%s: Cannot find jpeg settings", __func__); 624 return BAD_VALUE; 625 } 626 627 qcamera_hal3_jpeg_data_t *jpeg_job = 628 (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t)); 629 if (jpeg_job == NULL) { 630 ALOGE("%s: No memory for jpeg job", __func__); 631 return NO_MEMORY; 632 } 633 634 memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t)); 635 jpeg_job->src_frame = frame; 636 if(frame != job->src_frame) 637 jpeg_job->src_reproc_frame = job->src_frame; 638 if (NULL == job->fwk_src_frame) { 639 jpeg_job->metadata = job->metadata; 640 } else { 641 jpeg_job->metadata = 642 (metadata_buffer_t *) job->fwk_src_frame->metadata_buffer.buffer; 643 jpeg_job->fwk_src_buffer = job->fwk_src_frame; 644 } 645 jpeg_job->src_metadata = job->src_metadata; 646 jpeg_job->jpeg_settings = job->jpeg_settings; 647 648 // free pp job buf 649 free(job); 650 651 // enqueu reprocessed frame to jpeg input queue 652 m_inputJpegQ.enqueue((void *)jpeg_job); 653 654 // wait up data proc thread 655 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 656 657 return NO_ERROR; 658 } 659 660 /*=========================================================================== 661 * FUNCTION : findJpegJobByJobId 662 * 663 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID 664 * 665 * PARAMETERS : 666 * @jobId : job Id of the job 667 * 668 * RETURN : ptr to a jpeg job struct. NULL if not found. 669 * 670 * NOTE : Currently only one job is sending to mm-jpeg-interface for jpeg 671 * encoding. Therefore simply dequeue from the ongoing Jpeg Queue 672 * will serve the purpose to find the jpeg job. 673 *==========================================================================*/ 674 qcamera_hal3_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId) 675 { 676 qcamera_hal3_jpeg_data_t * job = NULL; 677 if (jobId == 0) { 678 ALOGE("%s: not a valid jpeg jobId", __func__); 679 return NULL; 680 } 681 682 // currely only one jpeg job ongoing, so simply dequeue the head 683 job = (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue(); 684 return job; 685 } 686 687 /*=========================================================================== 688 * FUNCTION : releasePPInputData 689 * 690 * DESCRIPTION: callback function to release post process input data node 691 * 692 * PARAMETERS : 693 * @data : ptr to post process input data 694 * @user_data : user data ptr (QCamera3Reprocessor) 695 * 696 * RETURN : None 697 *==========================================================================*/ 698 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data) 699 { 700 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data; 701 if (NULL != pme) { 702 pme->releaseSuperBuf((mm_camera_super_buf_t *)data); 703 } 704 } 705 706 /*=========================================================================== 707 * FUNCTION : releaseMetaData 708 * 709 * DESCRIPTION: callback function to release metadata camera buffer 710 * 711 * PARAMETERS : 712 * @data : ptr to post process input data 713 * @user_data : user data ptr (QCamera3Reprocessor) 714 * 715 * RETURN : None 716 *==========================================================================*/ 717 void QCamera3PostProcessor::releaseMetadata(void *data, void *user_data) 718 { 719 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data; 720 if (NULL != pme) { 721 pme->m_parent->metadataBufDone((mm_camera_super_buf_t *)data); 722 } 723 } 724 725 /*=========================================================================== 726 * FUNCTION : releaseJpegData 727 * 728 * DESCRIPTION: callback function to release jpeg job node 729 * 730 * PARAMETERS : 731 * @data : ptr to ongoing jpeg job data 732 * @user_data : user data ptr (QCamera3Reprocessor) 733 * 734 * RETURN : None 735 *==========================================================================*/ 736 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data) 737 { 738 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data; 739 if (NULL != pme) { 740 pme->releaseJpegJobData((qcamera_hal3_jpeg_data_t *)data); 741 } 742 } 743 744 /*=========================================================================== 745 * FUNCTION : releaseOngoingPPData 746 * 747 * DESCRIPTION: callback function to release ongoing postprocess job node 748 * 749 * PARAMETERS : 750 * @data : ptr to onging postprocess job 751 * @user_data : user data ptr (QCamera3Reprocessor) 752 * 753 * RETURN : None 754 *==========================================================================*/ 755 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data) 756 { 757 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data; 758 if (NULL != pme) { 759 qcamera_hal3_pp_data_t *pp_job = (qcamera_hal3_pp_data_t *)data; 760 if (NULL != pp_job->src_frame) { 761 pme->releaseSuperBuf(pp_job->src_frame); 762 free(pp_job->src_frame); 763 if (NULL != pp_job->src_metadata) { 764 pme->m_parent->metadataBufDone(pp_job->src_metadata); 765 free(pp_job->src_metadata); 766 } 767 pp_job->src_frame = NULL; 768 pp_job->metadata = NULL; 769 } 770 771 if (NULL != pp_job->fwk_src_frame) { 772 free(pp_job->fwk_src_frame); 773 pp_job->fwk_src_frame = NULL; 774 } 775 } 776 } 777 778 /*=========================================================================== 779 * FUNCTION : releaseSuperBuf 780 * 781 * DESCRIPTION: function to release a superbuf frame by returning back to kernel 782 * 783 * PARAMETERS : 784 * @super_buf : ptr to the superbuf frame 785 * 786 * RETURN : None 787 *==========================================================================*/ 788 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf) 789 { 790 if (NULL != super_buf) { 791 if (m_parent != NULL) { 792 m_parent->bufDone(super_buf); 793 } 794 } 795 } 796 797 /*=========================================================================== 798 * FUNCTION : releaseOfflineBuffers 799 * 800 * DESCRIPTION: function to release/unmap offline buffers if any 801 * 802 * PARAMETERS : None 803 * 804 * RETURN : int32_t type of status 805 * NO_ERROR -- success 806 * none-zero failure code 807 *==========================================================================*/ 808 int32_t QCamera3PostProcessor::releaseOfflineBuffers() 809 { 810 int32_t rc = NO_ERROR; 811 812 if(NULL != m_pReprocChannel) { 813 rc = m_pReprocChannel->unmapOfflineBuffers(false); 814 } 815 816 return rc; 817 } 818 819 /*=========================================================================== 820 * FUNCTION : releaseJpegJobData 821 * 822 * DESCRIPTION: function to release internal resources in jpeg job struct 823 * 824 * PARAMETERS : 825 * @job : ptr to jpeg job struct 826 * 827 * RETURN : None 828 * 829 * NOTE : original source frame need to be queued back to kernel for 830 * future use. Output buf of jpeg job need to be released since 831 * it's allocated for each job. Exif object need to be deleted. 832 *==========================================================================*/ 833 void QCamera3PostProcessor::releaseJpegJobData(qcamera_hal3_jpeg_data_t *job) 834 { 835 ATRACE_CALL(); 836 int32_t rc = NO_ERROR; 837 CDBG("%s: E", __func__); 838 if (NULL != job) { 839 if (NULL != job->src_reproc_frame) { 840 free(job->src_reproc_frame); 841 job->src_reproc_frame = NULL; 842 } 843 844 if (NULL != job->src_frame) { 845 if (NULL != m_pReprocChannel) { 846 rc = m_pReprocChannel->bufDone(job->src_frame); 847 if (NO_ERROR != rc) 848 ALOGE("%s: bufDone error: %d", __func__, rc); 849 } 850 free(job->src_frame); 851 job->src_frame = NULL; 852 } 853 854 if (NULL != job->fwk_src_buffer) { 855 free(job->fwk_src_buffer); 856 job->fwk_src_buffer = NULL; 857 } else if (NULL != job->src_metadata) { 858 m_parent->metadataBufDone(job->src_metadata); 859 free(job->src_metadata); 860 job->src_metadata = NULL; 861 } 862 863 if (NULL != job->fwk_frame) { 864 free(job->fwk_frame); 865 job->fwk_frame = NULL; 866 } 867 868 if (NULL != job->pJpegExifObj) { 869 delete job->pJpegExifObj; 870 job->pJpegExifObj = NULL; 871 } 872 873 if (NULL != job->jpeg_settings) { 874 free(job->jpeg_settings); 875 job->jpeg_settings = NULL; 876 } 877 } 878 /* Additional trigger to process any pending jobs in the input queue */ 879 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 880 CDBG("%s: X", __func__); 881 } 882 883 /*=========================================================================== 884 * FUNCTION : getColorfmtFromImgFmt 885 * 886 * DESCRIPTION: function to return jpeg color format based on its image format 887 * 888 * PARAMETERS : 889 * @img_fmt : image format 890 * 891 * RETURN : jpeg color format that can be understandable by omx lib 892 *==========================================================================*/ 893 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt) 894 { 895 switch (img_fmt) { 896 case CAM_FORMAT_YUV_420_NV21: 897 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 898 case CAM_FORMAT_YUV_420_NV21_ADRENO: 899 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 900 case CAM_FORMAT_YUV_420_NV12: 901 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 902 case CAM_FORMAT_YUV_420_YV12: 903 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 904 case CAM_FORMAT_YUV_422_NV61: 905 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1; 906 case CAM_FORMAT_YUV_422_NV16: 907 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1; 908 default: 909 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 910 } 911 } 912 913 /*=========================================================================== 914 * FUNCTION : getJpegImgTypeFromImgFmt 915 * 916 * DESCRIPTION: function to return jpeg encode image type based on its image format 917 * 918 * PARAMETERS : 919 * @img_fmt : image format 920 * 921 * RETURN : return jpeg source image format (YUV or Bitstream) 922 *==========================================================================*/ 923 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt) 924 { 925 switch (img_fmt) { 926 case CAM_FORMAT_YUV_420_NV21: 927 case CAM_FORMAT_YUV_420_NV21_ADRENO: 928 case CAM_FORMAT_YUV_420_NV12: 929 case CAM_FORMAT_YUV_420_YV12: 930 case CAM_FORMAT_YUV_422_NV61: 931 case CAM_FORMAT_YUV_422_NV16: 932 return MM_JPEG_FMT_YUV; 933 default: 934 return MM_JPEG_FMT_YUV; 935 } 936 } 937 938 /*=========================================================================== 939 * FUNCTION : encodeFWKData 940 * 941 * DESCRIPTION: function to prepare encoding job information and send to 942 * mm-jpeg-interface to do the encoding job 943 * 944 * PARAMETERS : 945 * @jpeg_job_data : ptr to a struct saving job related information 946 * @needNewSess : flag to indicate if a new jpeg encoding session need 947 * to be created. After creation, this flag will be toggled 948 * 949 * RETURN : int32_t type of status 950 * NO_ERROR -- success 951 * none-zero failure code 952 *==========================================================================*/ 953 int32_t QCamera3PostProcessor::encodeFWKData(qcamera_hal3_jpeg_data_t *jpeg_job_data, 954 uint8_t &needNewSess) 955 { 956 CDBG("%s : E", __func__); 957 int32_t ret = NO_ERROR; 958 mm_jpeg_job_t jpg_job; 959 uint32_t jobId = 0; 960 qcamera_fwk_input_pp_data_t *recvd_frame = NULL; 961 metadata_buffer_t *metadata = NULL; 962 jpeg_settings_t *jpeg_settings = NULL; 963 QCamera3HardwareInterface* hal_obj = NULL; 964 965 if (NULL == jpeg_job_data) { 966 ALOGE("%s: Invalid jpeg job", __func__); 967 return BAD_VALUE; 968 } 969 970 recvd_frame = jpeg_job_data->fwk_frame; 971 if (NULL == recvd_frame) { 972 ALOGE("%s: Invalid input buffer", __func__); 973 return BAD_VALUE; 974 } 975 976 metadata = jpeg_job_data->metadata; 977 if (NULL == metadata) { 978 ALOGE("%s: Invalid metadata buffer", __func__); 979 return BAD_VALUE; 980 } 981 982 jpeg_settings = jpeg_job_data->jpeg_settings; 983 if (NULL == jpeg_settings) { 984 ALOGE("%s: Invalid jpeg settings buffer", __func__); 985 return BAD_VALUE; 986 } 987 988 if ((NULL != jpeg_job_data->src_frame) && (NULL != jpeg_job_data->src_frame)) { 989 ALOGE("%s: Unsupported case both framework and camera source buffers are invalid!", 990 __func__); 991 return BAD_VALUE; 992 } 993 994 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData; 995 996 if (mJpegClientHandle <= 0) { 997 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__); 998 return UNKNOWN_ERROR; 999 } 1000 1001 cam_dimension_t src_dim; 1002 memset(&src_dim, 0, sizeof(cam_dimension_t)); 1003 src_dim.width = recvd_frame->reproc_config.input_stream_dim.width; 1004 src_dim.height = recvd_frame->reproc_config.input_stream_dim.height; 1005 1006 cam_dimension_t dst_dim; 1007 memset(&dst_dim, 0, sizeof(cam_dimension_t)); 1008 dst_dim.width = recvd_frame->reproc_config.output_stream_dim.width; 1009 dst_dim.height = recvd_frame->reproc_config.output_stream_dim.height; 1010 1011 CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess); 1012 if (needNewSess) { 1013 //creating a new session, so we must destroy the old one 1014 if ( 0 < mJpegSessionId ) { 1015 ret = mJpegHandle.destroy_session(mJpegSessionId); 1016 if (ret != NO_ERROR) { 1017 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d", 1018 __func__, mJpegSessionId); 1019 return ret; 1020 } 1021 mJpegSessionId = 0; 1022 } 1023 // create jpeg encoding session 1024 mm_jpeg_encode_params_t encodeParam; 1025 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t)); 1026 encodeParam.main_dim.src_dim = src_dim; 1027 encodeParam.main_dim.dst_dim = dst_dim; 1028 encodeParam.thumb_dim.src_dim = src_dim; 1029 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size; 1030 1031 getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings); 1032 CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__, 1033 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs); 1034 1035 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId); 1036 if (ret != NO_ERROR) { 1037 ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret); 1038 return ret; 1039 } 1040 needNewSess = FALSE; 1041 } 1042 1043 // Fill in new job 1044 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t)); 1045 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE; 1046 jpg_job.encode_job.session_id = mJpegSessionId; 1047 jpg_job.encode_job.src_index = 0; 1048 jpg_job.encode_job.dst_index = 0; 1049 1050 cam_rect_t crop; 1051 memset(&crop, 0, sizeof(cam_rect_t)); 1052 //TBD_later - Zoom event removed in stream 1053 //main_stream->getCropInfo(crop); 1054 1055 // main dim 1056 jpg_job.encode_job.main_dim.src_dim = src_dim; 1057 jpg_job.encode_job.main_dim.dst_dim = dst_dim; 1058 jpg_job.encode_job.main_dim.crop = crop; 1059 1060 // get exif data 1061 QCamera3Exif *pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings); 1062 jpeg_job_data->pJpegExifObj = pJpegExifObj; 1063 if (pJpegExifObj != NULL) { 1064 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries(); 1065 jpg_job.encode_job.exif_info.numOfEntries = 1066 pJpegExifObj->getNumOfEntries(); 1067 } 1068 1069 // thumbnail dim 1070 CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded); 1071 if (m_bThumbnailNeeded == TRUE) { 1072 memset(&crop, 0, sizeof(cam_rect_t)); 1073 jpg_job.encode_job.thumb_dim.dst_dim = 1074 jpeg_settings->thumbnail_size; 1075 1076 if (!hal_obj->needRotationReprocess()) { 1077 jpg_job.encode_job.rotation = 1078 jpeg_settings->jpeg_orientation; 1079 CDBG_HIGH("%s: jpeg rotation is set to %d", __func__, 1080 jpg_job.encode_job.rotation); 1081 } else if (jpeg_settings->jpeg_orientation == 90 || 1082 jpeg_settings->jpeg_orientation == 270) { 1083 //swap the thumbnail destination width and height if it has 1084 //already been rotated 1085 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width; 1086 jpg_job.encode_job.thumb_dim.dst_dim.width = 1087 jpg_job.encode_job.thumb_dim.dst_dim.height; 1088 jpg_job.encode_job.thumb_dim.dst_dim.height = temp; 1089 } 1090 jpg_job.encode_job.thumb_dim.src_dim = src_dim; 1091 jpg_job.encode_job.thumb_dim.crop = crop; 1092 jpg_job.encode_job.thumb_index = 0; 1093 } 1094 1095 if (metadata != NULL) { 1096 //Fill in the metadata passed as parameter 1097 jpg_job.encode_job.p_metadata = metadata; 1098 } else { 1099 ALOGE("%s: Metadata is null", __func__); 1100 } 1101 1102 jpg_job.encode_job.hal_version = CAM_HAL_V3; 1103 1104 //Start jpeg encoding 1105 ret = mJpegHandle.start_job(&jpg_job, &jobId); 1106 if (ret == NO_ERROR) { 1107 // remember job info 1108 jpeg_job_data->jobId = jobId; 1109 } 1110 1111 CDBG("%s : X", __func__); 1112 return ret; 1113 } 1114 1115 /*=========================================================================== 1116 * FUNCTION : encodeData 1117 * 1118 * DESCRIPTION: function to prepare encoding job information and send to 1119 * mm-jpeg-interface to do the encoding job 1120 * 1121 * PARAMETERS : 1122 * @jpeg_job_data : ptr to a struct saving job related information 1123 * @needNewSess : flag to indicate if a new jpeg encoding session need 1124 * to be created. After creation, this flag will be toggled 1125 * 1126 * RETURN : int32_t type of status 1127 * NO_ERROR -- success 1128 * none-zero failure code 1129 *==========================================================================*/ 1130 int32_t QCamera3PostProcessor::encodeData(qcamera_hal3_jpeg_data_t *jpeg_job_data, 1131 uint8_t &needNewSess) 1132 { 1133 ATRACE_CALL(); 1134 CDBG("%s : E", __func__); 1135 int32_t ret = NO_ERROR; 1136 mm_jpeg_job_t jpg_job; 1137 uint32_t jobId = 0; 1138 QCamera3Stream *main_stream = NULL; 1139 mm_camera_buf_def_t *main_frame = NULL; 1140 QCamera3Channel *srcChannel = NULL; 1141 mm_camera_super_buf_t *recvd_frame = NULL; 1142 metadata_buffer_t *metadata = NULL; 1143 jpeg_settings_t *jpeg_settings = NULL; 1144 QCamera3HardwareInterface* hal_obj = NULL; 1145 bool needJpegRotation = false; 1146 1147 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData; 1148 recvd_frame = jpeg_job_data->src_frame; 1149 metadata = jpeg_job_data->metadata; 1150 jpeg_settings = jpeg_job_data->jpeg_settings; 1151 1152 CDBG("%s: encoding bufIndex: %u", __func__, 1153 jpeg_job_data->src_frame->bufs[0]->buf_idx); 1154 1155 QCamera3Channel *pChannel = NULL; 1156 // first check picture channel 1157 if (m_parent != NULL && 1158 m_parent->getMyHandle() == recvd_frame->ch_id) { 1159 pChannel = m_parent; 1160 } 1161 // check reprocess channel if not found 1162 if (pChannel == NULL) { 1163 if (m_pReprocChannel != NULL && 1164 m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) { 1165 pChannel = m_pReprocChannel; 1166 } 1167 } 1168 1169 srcChannel = pChannel; 1170 1171 if (srcChannel == NULL) { 1172 ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here", 1173 __func__, recvd_frame->ch_id); 1174 return BAD_VALUE; 1175 } 1176 1177 // find snapshot frame and thumnail frame 1178 //Note: In this version we will receive only snapshot frame. 1179 for (int i = 0; i < recvd_frame->num_bufs; i++) { 1180 QCamera3Stream *srcStream = 1181 srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id); 1182 if (srcStream != NULL) { 1183 switch (srcStream->getMyType()) { 1184 case CAM_STREAM_TYPE_SNAPSHOT: 1185 case CAM_STREAM_TYPE_OFFLINE_PROC: 1186 main_stream = srcStream; 1187 main_frame = recvd_frame->bufs[i]; 1188 break; 1189 default: 1190 break; 1191 } 1192 } 1193 } 1194 1195 if(NULL == main_frame){ 1196 ALOGE("%s : Main frame is NULL", __func__); 1197 return BAD_VALUE; 1198 } 1199 1200 QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info; 1201 if (NULL == memObj) { 1202 ALOGE("%s : Memeory Obj of main frame is NULL", __func__); 1203 return NO_MEMORY; 1204 } 1205 1206 // clean and invalidate cache ops through mem obj of the frame 1207 memObj->cleanInvalidateCache(main_frame->buf_idx); 1208 1209 if (mJpegClientHandle <= 0) { 1210 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__); 1211 return UNKNOWN_ERROR; 1212 } 1213 cam_dimension_t src_dim; 1214 memset(&src_dim, 0, sizeof(cam_dimension_t)); 1215 main_stream->getFrameDimension(src_dim); 1216 1217 cam_dimension_t dst_dim; 1218 memset(&dst_dim, 0, sizeof(cam_dimension_t)); 1219 srcChannel->getStreamByIndex(0)->getFrameDimension(dst_dim); 1220 1221 needJpegRotation = hal_obj->needJpegRotation(); 1222 CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess); 1223 if (needNewSess) { 1224 //creating a new session, so we must destroy the old one 1225 if ( 0 < mJpegSessionId ) { 1226 ret = mJpegHandle.destroy_session(mJpegSessionId); 1227 if (ret != NO_ERROR) { 1228 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d", 1229 __func__, mJpegSessionId); 1230 return ret; 1231 } 1232 mJpegSessionId = 0; 1233 } 1234 // create jpeg encoding session 1235 mm_jpeg_encode_params_t encodeParam; 1236 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t)); 1237 getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings); 1238 CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__, 1239 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs); 1240 if (!needJpegRotation && 1241 (jpeg_settings->jpeg_orientation == 90 || 1242 jpeg_settings->jpeg_orientation == 270)) { 1243 //swap src width and height, stride and scanline due to rotation 1244 encodeParam.main_dim.src_dim.width = src_dim.height; 1245 encodeParam.main_dim.src_dim.height = src_dim.width; 1246 encodeParam.thumb_dim.src_dim.width = src_dim.height; 1247 encodeParam.thumb_dim.src_dim.height = src_dim.width; 1248 1249 int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride; 1250 encodeParam.src_main_buf[0].offset.mp[0].stride = 1251 encodeParam.src_main_buf[0].offset.mp[0].scanline; 1252 encodeParam.src_main_buf[0].offset.mp[0].scanline = temp; 1253 1254 temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride; 1255 encodeParam.src_thumb_buf[0].offset.mp[0].stride = 1256 encodeParam.src_thumb_buf[0].offset.mp[0].scanline; 1257 encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp; 1258 } else { 1259 encodeParam.main_dim.src_dim = src_dim; 1260 encodeParam.thumb_dim.src_dim = src_dim; 1261 } 1262 encodeParam.main_dim.dst_dim = dst_dim; 1263 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size; 1264 if (needJpegRotation) { 1265 encodeParam.rotation = jpeg_settings->jpeg_orientation; 1266 } 1267 1268 1269 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId); 1270 if (ret != NO_ERROR) { 1271 ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret); 1272 return ret; 1273 } 1274 needNewSess = FALSE; 1275 } 1276 1277 // Fill in new job 1278 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t)); 1279 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE; 1280 jpg_job.encode_job.session_id = mJpegSessionId; 1281 jpg_job.encode_job.src_index = main_frame->buf_idx; 1282 jpg_job.encode_job.dst_index = 0; 1283 1284 if (needJpegRotation) { 1285 jpg_job.encode_job.rotation = 1286 jpeg_settings->jpeg_orientation; 1287 CDBG("%s: %d: jpeg rotation is set to %d", __func__, __LINE__, 1288 jpg_job.encode_job.rotation); 1289 } 1290 1291 cam_rect_t crop; 1292 memset(&crop, 0, sizeof(cam_rect_t)); 1293 //TBD_later - Zoom event removed in stream 1294 //main_stream->getCropInfo(crop); 1295 1296 // main dim 1297 jpg_job.encode_job.main_dim.src_dim = src_dim; 1298 jpg_job.encode_job.main_dim.dst_dim = dst_dim; 1299 jpg_job.encode_job.main_dim.crop = crop; 1300 1301 // get exif data 1302 QCamera3Exif *pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings); 1303 jpeg_job_data->pJpegExifObj = pJpegExifObj; 1304 if (pJpegExifObj != NULL) { 1305 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries(); 1306 jpg_job.encode_job.exif_info.numOfEntries = 1307 pJpegExifObj->getNumOfEntries(); 1308 } 1309 1310 // thumbnail dim 1311 CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded); 1312 if (m_bThumbnailNeeded == TRUE) { 1313 memset(&crop, 0, sizeof(cam_rect_t)); 1314 jpg_job.encode_job.thumb_dim.dst_dim = 1315 jpeg_settings->thumbnail_size; 1316 1317 if (!needJpegRotation && 1318 (jpeg_settings->jpeg_orientation == 90 || 1319 jpeg_settings->jpeg_orientation == 270)) { 1320 //swap the thumbnail destination width and height if it has 1321 //already been rotated 1322 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width; 1323 jpg_job.encode_job.thumb_dim.dst_dim.width = 1324 jpg_job.encode_job.thumb_dim.dst_dim.height; 1325 jpg_job.encode_job.thumb_dim.dst_dim.height = temp; 1326 1327 jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height; 1328 jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width; 1329 } else { 1330 jpg_job.encode_job.thumb_dim.src_dim = src_dim; 1331 } 1332 jpg_job.encode_job.thumb_dim.crop = crop; 1333 jpg_job.encode_job.thumb_index = main_frame->buf_idx; 1334 } 1335 1336 if (metadata != NULL) { 1337 //Fill in the metadata passed as parameter 1338 jpg_job.encode_job.p_metadata = metadata; 1339 } else { 1340 ALOGE("%s: Metadata is null", __func__); 1341 } 1342 1343 jpg_job.encode_job.hal_version = CAM_HAL_V3; 1344 1345 //Start jpeg encoding 1346 ret = mJpegHandle.start_job(&jpg_job, &jobId); 1347 if (ret == NO_ERROR) { 1348 // remember job info 1349 jpeg_job_data->jobId = jobId; 1350 } 1351 1352 CDBG("%s : X", __func__); 1353 return ret; 1354 } 1355 1356 /*=========================================================================== 1357 * FUNCTION : dataProcessRoutine 1358 * 1359 * DESCRIPTION: data process routine that handles input data either from input 1360 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do 1361 * reprocess. 1362 * 1363 * PARAMETERS : 1364 * @data : user data ptr (QCamera3PostProcessor) 1365 * 1366 * RETURN : None 1367 *==========================================================================*/ 1368 void *QCamera3PostProcessor::dataProcessRoutine(void *data) 1369 { 1370 int running = 1; 1371 int ret; 1372 uint8_t is_active = FALSE; 1373 uint8_t needNewSess = TRUE; 1374 mm_camera_super_buf_t *meta_buffer = NULL; 1375 CDBG("%s: E", __func__); 1376 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data; 1377 QCameraCmdThread *cmdThread = &pme->m_dataProcTh; 1378 cmdThread->setName("cam_data_proc"); 1379 1380 do { 1381 do { 1382 ret = cam_sem_wait(&cmdThread->cmd_sem); 1383 if (ret != 0 && errno != EINVAL) { 1384 ALOGE("%s: cam_sem_wait error (%s)", 1385 __func__, strerror(errno)); 1386 return NULL; 1387 } 1388 } while (ret != 0); 1389 1390 // we got notified about new cmd avail in cmd queue 1391 camera_cmd_type_t cmd = cmdThread->getCmd(); 1392 switch (cmd) { 1393 case CAMERA_CMD_TYPE_START_DATA_PROC: 1394 CDBG_HIGH("%s: start data proc", __func__); 1395 is_active = TRUE; 1396 needNewSess = TRUE; 1397 1398 pme->m_ongoingPPQ.init(); 1399 pme->m_inputJpegQ.init(); 1400 pme->m_inputPPQ.init(); 1401 pme->m_inputFWKPPQ.init(); 1402 pme->m_inputRawQ.init(); 1403 pme->m_inputMetaQ.init(); 1404 cam_sem_post(&cmdThread->sync_sem); 1405 1406 break; 1407 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 1408 { 1409 CDBG_HIGH("%s: stop data proc", __func__); 1410 is_active = FALSE; 1411 1412 // cancel all ongoing jpeg jobs 1413 qcamera_hal3_jpeg_data_t *jpeg_job = 1414 (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1415 while (jpeg_job != NULL) { 1416 pme->mJpegHandle.abort_job(jpeg_job->jobId); 1417 1418 pme->releaseJpegJobData(jpeg_job); 1419 free(jpeg_job); 1420 1421 jpeg_job = (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1422 } 1423 1424 // destroy jpeg encoding session 1425 if ( 0 < pme->mJpegSessionId ) { 1426 pme->mJpegHandle.destroy_session(pme->mJpegSessionId); 1427 pme->mJpegSessionId = 0; 1428 } 1429 1430 needNewSess = TRUE; 1431 1432 // flush ongoing postproc Queue 1433 pme->m_ongoingPPQ.flush(); 1434 1435 // flush input jpeg Queue 1436 pme->m_inputJpegQ.flush(); 1437 1438 // flush input Postproc Queue 1439 pme->m_inputPPQ.flush(); 1440 1441 // flush framework input Postproc Queue 1442 pme->m_inputFWKPPQ.flush(); 1443 1444 // flush input raw Queue 1445 pme->m_inputRawQ.flush(); 1446 1447 pme->m_inputMetaQ.flush(); 1448 1449 // signal cmd is completed 1450 cam_sem_post(&cmdThread->sync_sem); 1451 } 1452 break; 1453 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 1454 { 1455 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active); 1456 /* needNewSess is set to TRUE as postproc is not re-STARTed 1457 * anymore for every captureRequest */ 1458 needNewSess = TRUE; 1459 if (is_active == TRUE) { 1460 // check if there is any ongoing jpeg jobs 1461 if (pme->m_ongoingJpegQ.isEmpty()) { 1462 CDBG("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__); 1463 // no ongoing jpeg job, we are fine to send jpeg encoding job 1464 qcamera_hal3_jpeg_data_t *jpeg_job = 1465 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 1466 1467 if (NULL != jpeg_job) { 1468 // add into ongoing jpeg job Q 1469 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job); 1470 1471 if (jpeg_job->fwk_frame) { 1472 ret = pme->encodeFWKData(jpeg_job, needNewSess); 1473 } else { 1474 ret = pme->encodeData(jpeg_job, needNewSess); 1475 } 1476 if (NO_ERROR != ret) { 1477 // dequeue the last one 1478 pme->m_ongoingJpegQ.dequeue(false); 1479 1480 pme->releaseJpegJobData(jpeg_job); 1481 free(jpeg_job); 1482 } 1483 } 1484 } 1485 1486 // check if there are any framework pp jobs 1487 if (!pme->m_inputFWKPPQ.isEmpty()) { 1488 qcamera_fwk_input_pp_data_t *fwk_frame = 1489 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue(); 1490 if (NULL != fwk_frame) { 1491 qcamera_hal3_pp_data_t *pp_job = 1492 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t)); 1493 jpeg_settings_t *jpeg_settings = 1494 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue(); 1495 if (pp_job != NULL) { 1496 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t)); 1497 pp_job->jpeg_settings = jpeg_settings; 1498 if (pme->m_pReprocChannel != NULL) { 1499 if (NO_ERROR != pme->m_pReprocChannel->extractCrop(fwk_frame)) { 1500 ALOGE("%s: Failed to extract output crop", __func__); 1501 } 1502 // add into ongoing PP job Q 1503 pp_job->fwk_src_frame = fwk_frame; 1504 pme->m_ongoingPPQ.enqueue((void *)pp_job); 1505 ret = pme->m_pReprocChannel->doReprocessOffline(fwk_frame); 1506 if (NO_ERROR != ret) { 1507 // remove from ongoing PP job Q 1508 pme->m_ongoingPPQ.dequeue(false); 1509 } 1510 } else { 1511 ALOGE("%s: Reprocess channel is NULL", __func__); 1512 ret = -1; 1513 } 1514 } else { 1515 ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__); 1516 ret = -1; 1517 } 1518 1519 if (0 != ret) { 1520 // free pp_job 1521 if (pp_job != NULL) { 1522 free(pp_job); 1523 } 1524 // free frame 1525 if (fwk_frame != NULL) { 1526 free(fwk_frame); 1527 } 1528 } 1529 } 1530 } 1531 1532 CDBG_HIGH("%s: dequeuing pp frame", __func__); 1533 pthread_mutex_lock(&pme->mReprocJobLock); 1534 if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) { 1535 mm_camera_super_buf_t *pp_frame = 1536 (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 1537 meta_buffer = 1538 (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue(); 1539 jpeg_settings_t *jpeg_settings = 1540 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue(); 1541 pthread_mutex_unlock(&pme->mReprocJobLock); 1542 qcamera_hal3_pp_data_t *pp_job = 1543 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t)); 1544 if (pp_job != NULL) { 1545 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t)); 1546 pp_job->src_frame = pp_frame; 1547 pp_job->src_metadata = meta_buffer; 1548 pp_job->metadata = 1549 (metadata_buffer_t *)meta_buffer->bufs[0]->buffer; 1550 pp_job->jpeg_settings = jpeg_settings; 1551 pme->m_ongoingPPQ.enqueue((void *)pp_job); 1552 if (pme->m_pReprocChannel != NULL) { 1553 qcamera_fwk_input_pp_data_t fwk_frame; 1554 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t)); 1555 ret = pme->m_pReprocChannel->extractFrameCropAndRotation( 1556 pp_frame, meta_buffer->bufs[0], 1557 pp_job->jpeg_settings, 1558 fwk_frame); 1559 if (NO_ERROR == ret) { 1560 // add into ongoing PP job Q 1561 ret = pme->m_pReprocChannel->doReprocessOffline( 1562 &fwk_frame); 1563 if (NO_ERROR != ret) { 1564 // remove from ongoing PP job Q 1565 pme->m_ongoingPPQ.dequeue(false); 1566 } 1567 } 1568 } else { 1569 CDBG_HIGH("%s: No reprocess. Calling processPPData directly", 1570 __func__); 1571 ret = pme->processPPData(pp_frame); 1572 } 1573 } else { 1574 ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__); 1575 ret = -1; 1576 } 1577 1578 if (0 != ret) { 1579 // free pp_job 1580 if (pp_job != NULL) { 1581 free(pp_job); 1582 } 1583 // free frame 1584 if (pp_frame != NULL) { 1585 pme->releaseSuperBuf(pp_frame); 1586 free(pp_frame); 1587 } 1588 //free metadata 1589 if (NULL != meta_buffer) { 1590 pme->m_parent->metadataBufDone(meta_buffer); 1591 free(meta_buffer); 1592 } 1593 } 1594 } else { 1595 pthread_mutex_unlock(&pme->mReprocJobLock); 1596 } 1597 } else { 1598 // not active, simply return buf and do no op 1599 qcamera_hal3_jpeg_data_t *jpeg_job = 1600 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 1601 if (NULL != jpeg_job) { 1602 free(jpeg_job); 1603 } 1604 mm_camera_super_buf_t *super_buf; 1605 super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 1606 if (NULL != super_buf) { 1607 pme->releaseSuperBuf(super_buf); 1608 free(super_buf); 1609 } 1610 super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 1611 if (NULL != super_buf) { 1612 pme->releaseSuperBuf(super_buf); 1613 free(super_buf); 1614 } 1615 mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue(); 1616 if (metadata != NULL) { 1617 pme->m_parent->metadataBufDone(metadata); 1618 free(metadata); 1619 } 1620 qcamera_fwk_input_pp_data_t *fwk_frame = 1621 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue(); 1622 if (NULL != fwk_frame) { 1623 free(fwk_frame); 1624 } 1625 } 1626 } 1627 break; 1628 case CAMERA_CMD_TYPE_EXIT: 1629 running = 0; 1630 break; 1631 default: 1632 break; 1633 } 1634 } while (running); 1635 CDBG("%s: X", __func__); 1636 return NULL; 1637 } 1638 1639 /*=========================================================================== 1640 * FUNCTION : QCamera3Exif 1641 * 1642 * DESCRIPTION: constructor of QCamera3Exif 1643 * 1644 * PARAMETERS : None 1645 * 1646 * RETURN : None 1647 *==========================================================================*/ 1648 QCamera3Exif::QCamera3Exif() 1649 : m_nNumEntries(0) 1650 { 1651 memset(m_Entries, 0, sizeof(m_Entries)); 1652 } 1653 1654 /*=========================================================================== 1655 * FUNCTION : ~QCamera3Exif 1656 * 1657 * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr. 1658 * 1659 * PARAMETERS : None 1660 * 1661 * RETURN : None 1662 *==========================================================================*/ 1663 QCamera3Exif::~QCamera3Exif() 1664 { 1665 for (uint32_t i = 0; i < m_nNumEntries; i++) { 1666 switch (m_Entries[i].tag_entry.type) { 1667 case EXIF_BYTE: 1668 { 1669 if (m_Entries[i].tag_entry.count > 1 && 1670 m_Entries[i].tag_entry.data._bytes != NULL) { 1671 free(m_Entries[i].tag_entry.data._bytes); 1672 m_Entries[i].tag_entry.data._bytes = NULL; 1673 } 1674 } 1675 break; 1676 case EXIF_ASCII: 1677 { 1678 if (m_Entries[i].tag_entry.data._ascii != NULL) { 1679 free(m_Entries[i].tag_entry.data._ascii); 1680 m_Entries[i].tag_entry.data._ascii = NULL; 1681 } 1682 } 1683 break; 1684 case EXIF_SHORT: 1685 { 1686 if (m_Entries[i].tag_entry.count > 1 && 1687 m_Entries[i].tag_entry.data._shorts != NULL) { 1688 free(m_Entries[i].tag_entry.data._shorts); 1689 m_Entries[i].tag_entry.data._shorts = NULL; 1690 } 1691 } 1692 break; 1693 case EXIF_LONG: 1694 { 1695 if (m_Entries[i].tag_entry.count > 1 && 1696 m_Entries[i].tag_entry.data._longs != NULL) { 1697 free(m_Entries[i].tag_entry.data._longs); 1698 m_Entries[i].tag_entry.data._longs = NULL; 1699 } 1700 } 1701 break; 1702 case EXIF_RATIONAL: 1703 { 1704 if (m_Entries[i].tag_entry.count > 1 && 1705 m_Entries[i].tag_entry.data._rats != NULL) { 1706 free(m_Entries[i].tag_entry.data._rats); 1707 m_Entries[i].tag_entry.data._rats = NULL; 1708 } 1709 } 1710 break; 1711 case EXIF_UNDEFINED: 1712 { 1713 if (m_Entries[i].tag_entry.data._undefined != NULL) { 1714 free(m_Entries[i].tag_entry.data._undefined); 1715 m_Entries[i].tag_entry.data._undefined = NULL; 1716 } 1717 } 1718 break; 1719 case EXIF_SLONG: 1720 { 1721 if (m_Entries[i].tag_entry.count > 1 && 1722 m_Entries[i].tag_entry.data._slongs != NULL) { 1723 free(m_Entries[i].tag_entry.data._slongs); 1724 m_Entries[i].tag_entry.data._slongs = NULL; 1725 } 1726 } 1727 break; 1728 case EXIF_SRATIONAL: 1729 { 1730 if (m_Entries[i].tag_entry.count > 1 && 1731 m_Entries[i].tag_entry.data._srats != NULL) { 1732 free(m_Entries[i].tag_entry.data._srats); 1733 m_Entries[i].tag_entry.data._srats = NULL; 1734 } 1735 } 1736 break; 1737 default: 1738 ALOGE("%s: Error, Unknown type",__func__); 1739 break; 1740 } 1741 } 1742 } 1743 1744 /*=========================================================================== 1745 * FUNCTION : addEntry 1746 * 1747 * DESCRIPTION: function to add an entry to exif data 1748 * 1749 * PARAMETERS : 1750 * @tagid : exif tag ID 1751 * @type : data type 1752 * @count : number of data in uint of its type 1753 * @data : input data ptr 1754 * 1755 * RETURN : int32_t type of status 1756 * NO_ERROR -- success 1757 * none-zero failure code 1758 *==========================================================================*/ 1759 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid, 1760 exif_tag_type_t type, 1761 uint32_t count, 1762 void *data) 1763 { 1764 int32_t rc = NO_ERROR; 1765 if(m_nNumEntries >= MAX_HAL3_EXIF_TABLE_ENTRIES) { 1766 ALOGE("%s: Number of entries exceeded limit", __func__); 1767 return NO_MEMORY; 1768 } 1769 1770 m_Entries[m_nNumEntries].tag_id = tagid; 1771 m_Entries[m_nNumEntries].tag_entry.type = type; 1772 m_Entries[m_nNumEntries].tag_entry.count = count; 1773 m_Entries[m_nNumEntries].tag_entry.copy = 1; 1774 switch (type) { 1775 case EXIF_BYTE: 1776 { 1777 if (count > 1) { 1778 uint8_t *values = (uint8_t *)malloc(count); 1779 if (values == NULL) { 1780 ALOGE("%s: No memory for byte array", __func__); 1781 rc = NO_MEMORY; 1782 } else { 1783 memcpy(values, data, count); 1784 m_Entries[m_nNumEntries].tag_entry.data._bytes = values; 1785 } 1786 } else { 1787 m_Entries[m_nNumEntries].tag_entry.data._byte = 1788 *(uint8_t *)data; 1789 } 1790 } 1791 break; 1792 case EXIF_ASCII: 1793 { 1794 char *str = NULL; 1795 str = (char *)malloc(count + 1); 1796 if (str == NULL) { 1797 ALOGE("%s: No memory for ascii string", __func__); 1798 rc = NO_MEMORY; 1799 } else { 1800 memset(str, 0, count + 1); 1801 memcpy(str, data, count); 1802 m_Entries[m_nNumEntries].tag_entry.data._ascii = str; 1803 } 1804 } 1805 break; 1806 case EXIF_SHORT: 1807 { 1808 if (count > 1) { 1809 uint16_t *values = 1810 (uint16_t *)malloc(count * sizeof(uint16_t)); 1811 if (values == NULL) { 1812 ALOGE("%s: No memory for short array", __func__); 1813 rc = NO_MEMORY; 1814 } else { 1815 memcpy(values, data, count * sizeof(uint16_t)); 1816 m_Entries[m_nNumEntries].tag_entry.data._shorts =values; 1817 } 1818 } else { 1819 m_Entries[m_nNumEntries].tag_entry.data._short = 1820 *(uint16_t *)data; 1821 } 1822 } 1823 break; 1824 case EXIF_LONG: 1825 { 1826 if (count > 1) { 1827 uint32_t *values = 1828 (uint32_t *)malloc(count * sizeof(uint32_t)); 1829 if (values == NULL) { 1830 ALOGE("%s: No memory for long array", __func__); 1831 rc = NO_MEMORY; 1832 } else { 1833 memcpy(values, data, count * sizeof(uint32_t)); 1834 m_Entries[m_nNumEntries].tag_entry.data._longs = values; 1835 } 1836 } else { 1837 m_Entries[m_nNumEntries].tag_entry.data._long = 1838 *(uint32_t *)data; 1839 } 1840 } 1841 break; 1842 case EXIF_RATIONAL: 1843 { 1844 if (count > 1) { 1845 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t)); 1846 if (values == NULL) { 1847 ALOGE("%s: No memory for rational array", __func__); 1848 rc = NO_MEMORY; 1849 } else { 1850 memcpy(values, data, count * sizeof(rat_t)); 1851 m_Entries[m_nNumEntries].tag_entry.data._rats = values; 1852 } 1853 } else { 1854 m_Entries[m_nNumEntries].tag_entry.data._rat = 1855 *(rat_t *)data; 1856 } 1857 } 1858 break; 1859 case EXIF_UNDEFINED: 1860 { 1861 uint8_t *values = (uint8_t *)malloc(count); 1862 if (values == NULL) { 1863 ALOGE("%s: No memory for undefined array", __func__); 1864 rc = NO_MEMORY; 1865 } else { 1866 memcpy(values, data, count); 1867 m_Entries[m_nNumEntries].tag_entry.data._undefined = values; 1868 } 1869 } 1870 break; 1871 case EXIF_SLONG: 1872 { 1873 if (count > 1) { 1874 int32_t *values = 1875 (int32_t *)malloc(count * sizeof(int32_t)); 1876 if (values == NULL) { 1877 ALOGE("%s: No memory for signed long array", __func__); 1878 rc = NO_MEMORY; 1879 } else { 1880 memcpy(values, data, count * sizeof(int32_t)); 1881 m_Entries[m_nNumEntries].tag_entry.data._slongs =values; 1882 } 1883 } else { 1884 m_Entries[m_nNumEntries].tag_entry.data._slong = 1885 *(int32_t *)data; 1886 } 1887 } 1888 break; 1889 case EXIF_SRATIONAL: 1890 { 1891 if (count > 1) { 1892 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t)); 1893 if (values == NULL) { 1894 ALOGE("%s: No memory for sign rational array",__func__); 1895 rc = NO_MEMORY; 1896 } else { 1897 memcpy(values, data, count * sizeof(srat_t)); 1898 m_Entries[m_nNumEntries].tag_entry.data._srats = values; 1899 } 1900 } else { 1901 m_Entries[m_nNumEntries].tag_entry.data._srat = 1902 *(srat_t *)data; 1903 } 1904 } 1905 break; 1906 default: 1907 ALOGE("%s: Error, Unknown type",__func__); 1908 break; 1909 } 1910 1911 // Increase number of entries 1912 m_nNumEntries++; 1913 return rc; 1914 } 1915 1916 }; // namespace qcamera 1917