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