1 /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 #define LOG_TAG "QCameraPostProc" 31 32 // System dependencies 33 #include <fcntl.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <utils/Errors.h> 37 38 // Camera dependencies 39 #include "QCamera2HWI.h" 40 #include "QCameraPostProc.h" 41 #include "QCameraTrace.h" 42 43 extern "C" { 44 #include "mm_camera_dbg.h" 45 } 46 47 namespace qcamera { 48 49 const char *QCameraPostProcessor::STORE_LOCATION = "/sdcard/img_%d.jpg"; 50 51 #define FREE_JPEG_OUTPUT_BUFFER(ptr,cnt) \ 52 int jpeg_bufs; \ 53 for (jpeg_bufs = 0; jpeg_bufs < (int)cnt; jpeg_bufs++) { \ 54 if (ptr[jpeg_bufs] != NULL) { \ 55 free(ptr[jpeg_bufs]); \ 56 ptr[jpeg_bufs] = NULL; \ 57 } \ 58 } 59 60 /*=========================================================================== 61 * FUNCTION : QCameraPostProcessor 62 * 63 * DESCRIPTION: constructor of QCameraPostProcessor. 64 * 65 * PARAMETERS : 66 * @cam_ctrl : ptr to HWI object 67 * 68 * RETURN : None 69 *==========================================================================*/ 70 QCameraPostProcessor::QCameraPostProcessor(QCamera2HardwareInterface *cam_ctrl) 71 : m_parent(cam_ctrl), 72 mJpegCB(NULL), 73 mJpegUserData(NULL), 74 mJpegClientHandle(0), 75 mJpegSessionId(0), 76 m_pJpegExifObj(NULL), 77 m_bThumbnailNeeded(TRUE), 78 mPPChannelCount(0), 79 m_bInited(FALSE), 80 m_inputPPQ(releaseOngoingPPData, this), 81 m_ongoingPPQ(releaseOngoingPPData, this), 82 m_inputJpegQ(releaseJpegData, this), 83 m_ongoingJpegQ(releaseJpegData, this), 84 m_inputRawQ(releaseRawData, this), 85 mSaveFrmCnt(0), 86 mUseSaveProc(false), 87 mUseJpegBurst(false), 88 mJpegMemOpt(true), 89 m_JpegOutputMemCount(0), 90 mNewJpegSessionNeeded(true), 91 m_bufCountPPQ(0), 92 m_PPindex(0) 93 { 94 memset(&mJpegHandle, 0, sizeof(mJpegHandle)); 95 memset(&mJpegMpoHandle, 0, sizeof(mJpegMpoHandle)); 96 memset(&m_pJpegOutputMem, 0, sizeof(m_pJpegOutputMem)); 97 memset(mPPChannels, 0, sizeof(mPPChannels)); 98 m_DataMem = NULL; 99 mOfflineDataBufs = NULL; 100 pthread_mutex_init(&m_reprocess_lock,NULL); 101 } 102 103 /*=========================================================================== 104 * FUNCTION : ~QCameraPostProcessor 105 * 106 * DESCRIPTION: deconstructor of QCameraPostProcessor. 107 * 108 * PARAMETERS : None 109 * 110 * RETURN : None 111 *==========================================================================*/ 112 QCameraPostProcessor::~QCameraPostProcessor() 113 { 114 FREE_JPEG_OUTPUT_BUFFER(m_pJpegOutputMem,m_JpegOutputMemCount); 115 if (m_pJpegExifObj != NULL) { 116 delete m_pJpegExifObj; 117 m_pJpegExifObj = NULL; 118 } 119 for (int8_t i = 0; i < mPPChannelCount; i++) { 120 QCameraChannel *pChannel = mPPChannels[i]; 121 if ( pChannel != NULL ) { 122 pChannel->stop(); 123 delete pChannel; 124 pChannel = NULL; 125 } 126 } 127 mPPChannelCount = 0; 128 pthread_mutex_destroy(&m_reprocess_lock); 129 } 130 131 /*=========================================================================== 132 * FUNCTION : setJpegHandle 133 * 134 * DESCRIPTION: set JPEG client handles 135 * 136 * PARAMETERS : 137 * @pJpegHandle : JPEG ops handle 138 * @pJpegMpoHandle : MPO JPEG ops handle 139 * @clientHandle : JPEG client handle 140 * 141 * RETURN : int32_t type of status 142 * NO_ERROR -- success 143 * none-zero failure code 144 *==========================================================================*/ 145 int32_t QCameraPostProcessor::setJpegHandle(mm_jpeg_ops_t *pJpegHandle, 146 mm_jpeg_mpo_ops_t *pJpegMpoHandle, uint32_t clientHandle) 147 { 148 LOGH("E mJpegClientHandle: %d, clientHandle: %d", 149 mJpegClientHandle, clientHandle); 150 151 if(pJpegHandle) { 152 memcpy(&mJpegHandle, pJpegHandle, sizeof(mm_jpeg_ops_t)); 153 } 154 155 if(pJpegMpoHandle) { 156 memcpy(&mJpegMpoHandle, pJpegMpoHandle, sizeof(mm_jpeg_mpo_ops_t)); 157 } 158 mJpegClientHandle = clientHandle; 159 LOGH("X mJpegClientHandle: %d, clientHandle: %d", 160 mJpegClientHandle, clientHandle); 161 return NO_ERROR; 162 } 163 164 /*=========================================================================== 165 * FUNCTION : init 166 * 167 * DESCRIPTION: initialization of postprocessor 168 * 169 * PARAMETERS : 170 * @jpeg_cb : callback to handle jpeg event from mm-camera-interface 171 * @user_data : user data ptr for jpeg callback 172 * 173 * RETURN : int32_t type of status 174 * NO_ERROR -- success 175 * none-zero failure code 176 *==========================================================================*/ 177 int32_t QCameraPostProcessor::init(jpeg_encode_callback_t jpeg_cb, void *user_data) 178 { 179 mJpegCB = jpeg_cb; 180 mJpegUserData = user_data; 181 m_dataProcTh.launch(dataProcessRoutine, this); 182 m_saveProcTh.launch(dataSaveRoutine, this); 183 m_parent->mParameters.setReprocCount(); 184 m_bInited = TRUE; 185 return NO_ERROR; 186 } 187 188 /*=========================================================================== 189 * FUNCTION : deinit 190 * 191 * DESCRIPTION: de-initialization of postprocessor 192 * 193 * PARAMETERS : None 194 * 195 * RETURN : int32_t type of status 196 * NO_ERROR -- success 197 * none-zero failure code 198 *==========================================================================*/ 199 int32_t QCameraPostProcessor::deinit() 200 { 201 if (m_bInited == TRUE) { 202 m_dataProcTh.exit(); 203 m_saveProcTh.exit(); 204 m_bInited = FALSE; 205 } 206 return NO_ERROR; 207 } 208 209 /*=========================================================================== 210 * FUNCTION : start 211 * 212 * DESCRIPTION: start postprocessor. Data process thread and data notify thread 213 * will be launched. 214 * 215 * PARAMETERS : 216 * @pSrcChannel : source channel obj ptr that possibly needs reprocess 217 * 218 * RETURN : int32_t type of status 219 * NO_ERROR -- success 220 * none-zero failure code 221 * 222 * NOTE : if any reprocess is needed, a reprocess channel/stream 223 * will be started. 224 *==========================================================================*/ 225 int32_t QCameraPostProcessor::start(QCameraChannel *pSrcChannel) 226 { 227 char prop[PROPERTY_VALUE_MAX]; 228 int32_t rc = NO_ERROR; 229 QCameraChannel *pInputChannel = pSrcChannel; 230 231 LOGH("E "); 232 if (m_bInited == FALSE) { 233 LOGE("postproc not initialized yet"); 234 return UNKNOWN_ERROR; 235 } 236 237 if (m_DataMem != NULL) { 238 m_DataMem->release(m_DataMem); 239 m_DataMem = NULL; 240 } 241 242 if (pInputChannel == NULL) { 243 LOGE("Input Channel for pproc is NULL."); 244 return UNKNOWN_ERROR; 245 } 246 247 if ( m_parent->needReprocess() ) { 248 for (int8_t i = 0; i < mPPChannelCount; i++) { 249 // Delete previous reproc channel 250 QCameraReprocessChannel *pChannel = mPPChannels[i]; 251 if (pChannel != NULL) { 252 pChannel->stop(); 253 delete pChannel; 254 pChannel = NULL; 255 } 256 } 257 mPPChannelCount = 0; 258 259 m_bufCountPPQ = 0; 260 if (!m_parent->isLongshotEnabled()) { 261 m_parent->mParameters.setReprocCount(); 262 } 263 264 if (m_parent->mParameters.getManualCaptureMode() >= 265 CAM_MANUAL_CAPTURE_TYPE_3) { 266 mPPChannelCount = m_parent->mParameters.getReprocCount() - 1; 267 } else { 268 mPPChannelCount = m_parent->mParameters.getReprocCount(); 269 } 270 271 // Create all reproc channels and start channel 272 for (int8_t i = 0; i < mPPChannelCount; i++) { 273 mPPChannels[i] = m_parent->addReprocChannel(pInputChannel, i); 274 if (mPPChannels[i] == NULL) { 275 LOGE("cannot add multi reprocess channel i = %d", i); 276 return UNKNOWN_ERROR; 277 } 278 rc = mPPChannels[i]->start(); 279 if (rc != 0) { 280 LOGE("cannot start multi reprocess channel i = %d", i); 281 delete mPPChannels[i]; 282 mPPChannels[i] = NULL; 283 return UNKNOWN_ERROR; 284 } 285 pInputChannel = static_cast<QCameraChannel *>(mPPChannels[i]); 286 } 287 } 288 289 property_get("persist.camera.longshot.save", prop, "0"); 290 mUseSaveProc = atoi(prop) > 0 ? true : false; 291 292 m_PPindex = 0; 293 m_InputMetadata.clear(); 294 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, TRUE, FALSE); 295 m_parent->m_cbNotifier.startSnapshots(); 296 LOGH("X rc = %d", rc); 297 return rc; 298 } 299 300 /*=========================================================================== 301 * FUNCTION : stop 302 * 303 * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped. 304 * 305 * PARAMETERS : None 306 * 307 * RETURN : int32_t type of status 308 * NO_ERROR -- success 309 * none-zero failure code 310 * 311 * NOTE : reprocess channel will be stopped and deleted if there is any 312 *==========================================================================*/ 313 int32_t QCameraPostProcessor::stop() 314 { 315 if (m_bInited == TRUE) { 316 m_parent->m_cbNotifier.stopSnapshots(); 317 318 if (m_DataMem != NULL) { 319 m_DataMem->release(m_DataMem); 320 m_DataMem = NULL; 321 } 322 323 // dataProc Thread need to process "stop" as sync call because abort jpeg job should be a sync call 324 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE); 325 } 326 // stop reproc channel if exists 327 for (int8_t i = 0; i < mPPChannelCount; i++) { 328 QCameraReprocessChannel *pChannel = mPPChannels[i]; 329 if (pChannel != NULL) { 330 pChannel->stop(); 331 delete pChannel; 332 pChannel = NULL; 333 } 334 } 335 mPPChannelCount = 0; 336 m_PPindex = 0; 337 m_InputMetadata.clear(); 338 339 if (mOfflineDataBufs != NULL) { 340 mOfflineDataBufs->deallocate(); 341 delete mOfflineDataBufs; 342 mOfflineDataBufs = NULL; 343 } 344 return NO_ERROR; 345 } 346 347 /*=========================================================================== 348 * FUNCTION : createJpegSession 349 * 350 * DESCRIPTION: start JPEG session in parallel to reproces to reduce the KPI 351 * 352 * PARAMETERS : 353 * @pSrcChannel : source channel obj ptr that possibly needs reprocess 354 * 355 * RETURN : int32_t type of status 356 * NO_ERROR -- success 357 * none-zero failure code 358 *==========================================================================*/ 359 int32_t QCameraPostProcessor::createJpegSession(QCameraChannel *pSrcChannel) 360 { 361 int32_t rc = NO_ERROR; 362 363 LOGH("E "); 364 if (m_bInited == FALSE) { 365 LOGE("postproc not initialized yet"); 366 return UNKNOWN_ERROR; 367 } 368 369 if (pSrcChannel == NULL) { 370 LOGE("Input Channel for pproc is NULL."); 371 return UNKNOWN_ERROR; 372 } 373 374 if (mPPChannelCount > 0) { 375 QCameraChannel *pChannel = NULL; 376 int ppChannel_idx = mPPChannelCount - 1; 377 pChannel = m_parent->needReprocess() ? mPPChannels[ppChannel_idx] : 378 pSrcChannel; 379 QCameraStream *pSnapshotStream = NULL; 380 QCameraStream *pThumbStream = NULL; 381 bool thumb_stream_needed = ((!m_parent->isZSLMode() || 382 (m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT) == 383 m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_PREVIEW))) && 384 !m_parent->mParameters.generateThumbFromMain()); 385 386 if (pChannel == NULL) { 387 LOGE("Input Channel for pproc is NULL for index %d.", 388 ppChannel_idx); 389 return UNKNOWN_ERROR; 390 } 391 392 for (uint32_t i = 0; i < pChannel->getNumOfStreams(); ++i) { 393 QCameraStream *pStream = pChannel->getStreamByIndex(i); 394 395 if ( NULL == pStream ) { 396 break; 397 } 398 399 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 400 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { 401 pSnapshotStream = pStream; 402 } 403 404 if ((thumb_stream_needed) && 405 (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 406 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 407 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) || 408 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW))) { 409 pThumbStream = pStream; 410 } 411 } 412 413 // If thumbnail is not part of the reprocess channel, then 414 // try to get it from the source channel 415 if ((thumb_stream_needed) && (NULL == pThumbStream) && 416 (pChannel == mPPChannels[ppChannel_idx])) { 417 for (uint32_t i = 0; i < pSrcChannel->getNumOfStreams(); ++i) { 418 QCameraStream *pStream = pSrcChannel->getStreamByIndex(i); 419 420 if ( NULL == pStream ) { 421 break; 422 } 423 424 if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 425 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 426 pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 427 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW)) { 428 pThumbStream = pStream; 429 } 430 } 431 } 432 433 if ( NULL != pSnapshotStream ) { 434 mm_jpeg_encode_params_t encodeParam; 435 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t)); 436 rc = getJpegEncodingConfig(encodeParam, pSnapshotStream, pThumbStream); 437 if (rc != NO_ERROR) { 438 LOGE("error getting encoding config"); 439 return rc; 440 } 441 LOGH("[KPI Perf] : call jpeg create_session"); 442 443 rc = mJpegHandle.create_session(mJpegClientHandle, 444 &encodeParam, 445 &mJpegSessionId); 446 if (rc != NO_ERROR) { 447 LOGE("error creating a new jpeg encoding session"); 448 return rc; 449 } 450 mNewJpegSessionNeeded = false; 451 } 452 } 453 LOGH("X "); 454 return rc; 455 } 456 457 /*=========================================================================== 458 * FUNCTION : getJpegEncodingConfig 459 * 460 * DESCRIPTION: function to prepare encoding job information 461 * 462 * PARAMETERS : 463 * @encode_parm : param to be filled with encoding configuration 464 * 465 * RETURN : int32_t type of status 466 * NO_ERROR -- success 467 * none-zero failure code 468 *==========================================================================*/ 469 int32_t QCameraPostProcessor::getJpegEncodingConfig(mm_jpeg_encode_params_t& encode_parm, 470 QCameraStream *main_stream, 471 QCameraStream *thumb_stream) 472 { 473 LOGD("E"); 474 int32_t ret = NO_ERROR; 475 size_t out_size; 476 477 char prop[PROPERTY_VALUE_MAX]; 478 property_get("persist.camera.jpeg_burst", prop, "0"); 479 mUseJpegBurst = (atoi(prop) > 0) && !mUseSaveProc; 480 encode_parm.burst_mode = mUseJpegBurst; 481 482 cam_rect_t crop; 483 memset(&crop, 0, sizeof(cam_rect_t)); 484 main_stream->getCropInfo(crop); 485 486 cam_dimension_t src_dim, dst_dim; 487 memset(&src_dim, 0, sizeof(cam_dimension_t)); 488 memset(&dst_dim, 0, sizeof(cam_dimension_t)); 489 main_stream->getFrameDimension(src_dim); 490 491 bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled(); 492 if (hdr_output_crop && crop.height) { 493 dst_dim.height = crop.height; 494 } else { 495 dst_dim.height = src_dim.height; 496 } 497 if (hdr_output_crop && crop.width) { 498 dst_dim.width = crop.width; 499 } else { 500 dst_dim.width = src_dim.width; 501 } 502 503 // set rotation only when no online rotation or offline pp rotation is done before 504 if (!m_parent->needRotationReprocess()) { 505 encode_parm.rotation = m_parent->mParameters.getJpegRotation(); 506 } 507 508 encode_parm.main_dim.src_dim = src_dim; 509 encode_parm.main_dim.dst_dim = dst_dim; 510 511 m_dst_dim = dst_dim; 512 513 encode_parm.jpeg_cb = mJpegCB; 514 encode_parm.userdata = mJpegUserData; 515 516 m_bThumbnailNeeded = TRUE; // need encode thumbnail by default 517 // system property to disable the thumbnail encoding in order to reduce the power 518 // by default thumbnail encoding is set to TRUE and explicitly set this property to 519 // disable the thumbnail encoding 520 property_get("persist.camera.tn.disable", prop, "0"); 521 if (atoi(prop) == 1) { 522 m_bThumbnailNeeded = FALSE; 523 LOGH("m_bThumbnailNeeded is %d", m_bThumbnailNeeded); 524 } 525 cam_dimension_t thumbnailSize; 526 memset(&thumbnailSize, 0, sizeof(cam_dimension_t)); 527 m_parent->getThumbnailSize(thumbnailSize); 528 if (thumbnailSize.width == 0 || thumbnailSize.height == 0) { 529 // (0,0) means no thumbnail 530 m_bThumbnailNeeded = FALSE; 531 } 532 encode_parm.encode_thumbnail = m_bThumbnailNeeded; 533 534 // get color format 535 cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12; 536 main_stream->getFormat(img_fmt); 537 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt); 538 539 // get jpeg quality 540 uint32_t val = m_parent->getJpegQuality(); 541 if (0U < val) { 542 encode_parm.quality = val; 543 } else { 544 LOGH("Using default JPEG quality"); 545 encode_parm.quality = 85; 546 } 547 cam_frame_len_offset_t main_offset; 548 memset(&main_offset, 0, sizeof(cam_frame_len_offset_t)); 549 main_stream->getFrameOffset(main_offset); 550 551 // src buf config 552 QCameraMemory *pStreamMem = main_stream->getStreamBufs(); 553 if (pStreamMem == NULL) { 554 LOGE("cannot get stream bufs from main stream"); 555 ret = BAD_VALUE; 556 goto on_error; 557 } 558 encode_parm.num_src_bufs = pStreamMem->getCnt(); 559 for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) { 560 camera_memory_t *stream_mem = pStreamMem->getMemory(i, false); 561 if (stream_mem != NULL) { 562 encode_parm.src_main_buf[i].index = i; 563 encode_parm.src_main_buf[i].buf_size = stream_mem->size; 564 encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)stream_mem->data; 565 encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i); 566 encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV; 567 encode_parm.src_main_buf[i].offset = main_offset; 568 } 569 } 570 LOGI("Src Buffer cnt = %d, res = %dX%d len = %d rot = %d " 571 "src_dim = %dX%d dst_dim = %dX%d", 572 encode_parm.num_src_bufs, 573 main_offset.mp[0].width, main_offset.mp[0].height, 574 main_offset.frame_len, encode_parm.rotation, 575 src_dim.width, src_dim.height, 576 dst_dim.width, dst_dim.height); 577 578 if (m_bThumbnailNeeded == TRUE) { 579 m_parent->getThumbnailSize(encode_parm.thumb_dim.dst_dim); 580 581 if (thumb_stream == NULL) { 582 thumb_stream = main_stream; 583 } 584 if (((90 == m_parent->mParameters.getJpegRotation()) 585 || (270 == m_parent->mParameters.getJpegRotation())) 586 && (m_parent->needRotationReprocess())) { 587 // swap thumbnail dimensions 588 cam_dimension_t tmp_dim = encode_parm.thumb_dim.dst_dim; 589 encode_parm.thumb_dim.dst_dim.width = tmp_dim.height; 590 encode_parm.thumb_dim.dst_dim.height = tmp_dim.width; 591 } 592 pStreamMem = thumb_stream->getStreamBufs(); 593 if (pStreamMem == NULL) { 594 LOGE("cannot get stream bufs from thumb stream"); 595 ret = BAD_VALUE; 596 goto on_error; 597 } 598 cam_frame_len_offset_t thumb_offset; 599 memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t)); 600 thumb_stream->getFrameOffset(thumb_offset); 601 encode_parm.num_tmb_bufs = pStreamMem->getCnt(); 602 for (uint32_t i = 0; i < pStreamMem->getCnt(); i++) { 603 camera_memory_t *stream_mem = pStreamMem->getMemory(i, false); 604 if (stream_mem != NULL) { 605 encode_parm.src_thumb_buf[i].index = i; 606 encode_parm.src_thumb_buf[i].buf_size = stream_mem->size; 607 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)stream_mem->data; 608 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i); 609 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV; 610 encode_parm.src_thumb_buf[i].offset = thumb_offset; 611 } 612 } 613 cam_format_t img_fmt_thumb = CAM_FORMAT_YUV_420_NV12; 614 thumb_stream->getFormat(img_fmt_thumb); 615 encode_parm.thumb_color_format = getColorfmtFromImgFmt(img_fmt_thumb); 616 617 // crop is the same if frame is the same 618 if (thumb_stream != main_stream) { 619 memset(&crop, 0, sizeof(cam_rect_t)); 620 thumb_stream->getCropInfo(crop); 621 } 622 623 memset(&src_dim, 0, sizeof(cam_dimension_t)); 624 thumb_stream->getFrameDimension(src_dim); 625 encode_parm.thumb_dim.src_dim = src_dim; 626 627 if (!m_parent->needRotationReprocess()) { 628 encode_parm.thumb_rotation = m_parent->mParameters.getJpegRotation(); 629 } 630 encode_parm.thumb_dim.crop = crop; 631 encode_parm.thumb_from_postview = 632 !m_parent->mParameters.generateThumbFromMain() && 633 (img_fmt_thumb != CAM_FORMAT_YUV_420_NV12_UBWC) && 634 (m_parent->mParameters.useJpegExifRotation() || 635 m_parent->mParameters.getJpegRotation() == 0); 636 637 if (encode_parm.thumb_from_postview && 638 m_parent->mParameters.useJpegExifRotation()){ 639 encode_parm.thumb_rotation = 640 m_parent->mParameters.getJpegExifRotation(); 641 } 642 643 LOGI("Src THUMB buf_cnt = %d, res = %dX%d len = %d rot = %d " 644 "src_dim = %dX%d, dst_dim = %dX%d", 645 encode_parm.num_tmb_bufs, 646 thumb_offset.mp[0].width, thumb_offset.mp[0].height, 647 thumb_offset.frame_len, encode_parm.thumb_rotation, 648 encode_parm.thumb_dim.src_dim.width, 649 encode_parm.thumb_dim.src_dim.height, 650 encode_parm.thumb_dim.dst_dim.width, 651 encode_parm.thumb_dim.dst_dim.height); 652 } 653 654 encode_parm.num_dst_bufs = 1; 655 if (mUseJpegBurst) { 656 encode_parm.num_dst_bufs = MAX_JPEG_BURST; 657 } 658 encode_parm.get_memory = NULL; 659 out_size = main_offset.frame_len; 660 if (mJpegMemOpt) { 661 encode_parm.get_memory = getJpegMemory; 662 encode_parm.put_memory = releaseJpegMemory; 663 out_size = sizeof(omx_jpeg_ouput_buf_t); 664 encode_parm.num_dst_bufs = encode_parm.num_src_bufs; 665 } 666 m_JpegOutputMemCount = (uint32_t)encode_parm.num_dst_bufs; 667 for (uint32_t i = 0; i < m_JpegOutputMemCount; i++) { 668 if (m_pJpegOutputMem[i] != NULL) 669 free(m_pJpegOutputMem[i]); 670 omx_jpeg_ouput_buf_t omx_out_buf; 671 memset(&omx_out_buf, 0, sizeof(omx_jpeg_ouput_buf_t)); 672 omx_out_buf.handle = this; 673 // allocate output buf for jpeg encoding 674 m_pJpegOutputMem[i] = malloc(out_size); 675 676 if (NULL == m_pJpegOutputMem[i]) { 677 ret = NO_MEMORY; 678 LOGE("initHeapMem for jpeg, ret = NO_MEMORY"); 679 goto on_error; 680 } 681 682 if (mJpegMemOpt) { 683 memcpy(m_pJpegOutputMem[i], &omx_out_buf, sizeof(omx_out_buf)); 684 } 685 686 encode_parm.dest_buf[i].index = i; 687 encode_parm.dest_buf[i].buf_size = main_offset.frame_len; 688 encode_parm.dest_buf[i].buf_vaddr = (uint8_t *)m_pJpegOutputMem[i]; 689 encode_parm.dest_buf[i].fd = -1; 690 encode_parm.dest_buf[i].format = MM_JPEG_FMT_YUV; 691 encode_parm.dest_buf[i].offset = main_offset; 692 } 693 694 LOGD("X"); 695 return NO_ERROR; 696 697 on_error: 698 FREE_JPEG_OUTPUT_BUFFER(m_pJpegOutputMem, m_JpegOutputMemCount); 699 700 LOGD("X with error %d", ret); 701 return ret; 702 } 703 704 /*=========================================================================== 705 * FUNCTION : sendEvtNotify 706 * 707 * DESCRIPTION: send event notify through notify callback registered by upper layer 708 * 709 * PARAMETERS : 710 * @msg_type: msg type of notify 711 * @ext1 : extension 712 * @ext2 : extension 713 * 714 * RETURN : int32_t type of status 715 * NO_ERROR -- success 716 * none-zero failure code 717 *==========================================================================*/ 718 int32_t QCameraPostProcessor::sendEvtNotify(int32_t msg_type, 719 int32_t ext1, 720 int32_t ext2) 721 { 722 return m_parent->sendEvtNotify(msg_type, ext1, ext2); 723 } 724 725 /*=========================================================================== 726 * FUNCTION : sendDataNotify 727 * 728 * DESCRIPTION: enqueue data into dataNotify thread 729 * 730 * PARAMETERS : 731 * @msg_type: data callback msg type 732 * @data : ptr to data memory struct 733 * @index : index to data buffer 734 * @metadata: ptr to meta data buffer if there is any 735 * @release_data : ptr to struct indicating if data need to be released 736 * after notify 737 * @super_buf_frame_idx : super buffer frame index 738 * 739 * RETURN : int32_t type of status 740 * NO_ERROR -- success 741 * none-zero failure code 742 *==========================================================================*/ 743 int32_t QCameraPostProcessor::sendDataNotify(int32_t msg_type, 744 camera_memory_t *data, 745 uint8_t index, 746 camera_frame_metadata_t *metadata, 747 qcamera_release_data_t *release_data, 748 uint32_t super_buf_frame_idx) 749 { 750 qcamera_data_argm_t *data_cb = (qcamera_data_argm_t *)malloc(sizeof(qcamera_data_argm_t)); 751 if (NULL == data_cb) { 752 LOGE("no mem for acamera_data_argm_t"); 753 return NO_MEMORY; 754 } 755 memset(data_cb, 0, sizeof(qcamera_data_argm_t)); 756 data_cb->msg_type = msg_type; 757 data_cb->data = data; 758 data_cb->index = index; 759 data_cb->metadata = metadata; 760 if (release_data != NULL) { 761 data_cb->release_data = *release_data; 762 } 763 764 qcamera_callback_argm_t cbArg; 765 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 766 cbArg.cb_type = QCAMERA_DATA_SNAPSHOT_CALLBACK; 767 cbArg.msg_type = msg_type; 768 cbArg.data = data; 769 cbArg.metadata = metadata; 770 cbArg.user_data = data_cb; 771 cbArg.cookie = this; 772 cbArg.release_cb = releaseNotifyData; 773 cbArg.frame_index = super_buf_frame_idx; 774 int rc = m_parent->m_cbNotifier.notifyCallback(cbArg); 775 if ( NO_ERROR != rc ) { 776 LOGE("Error enqueuing jpeg data into notify queue"); 777 releaseNotifyData(data_cb, this, UNKNOWN_ERROR); 778 return UNKNOWN_ERROR; 779 } 780 781 return rc; 782 } 783 784 /*=========================================================================== 785 * FUNCTION : validatePostProcess 786 * 787 * DESCRIPTION: Verify output buffer count of pp module 788 * 789 * PARAMETERS : 790 * @frame : process frame received from mm-camera-interface 791 * 792 * RETURN : bool type of status 793 * TRUE -- success 794 * FALSE failure 795 *==========================================================================*/ 796 bool QCameraPostProcessor::validatePostProcess(mm_camera_super_buf_t *frame) 797 { 798 bool status = TRUE; 799 QCameraChannel *pChannel = NULL; 800 QCameraReprocessChannel *m_pReprocChannel = NULL; 801 802 if (frame == NULL) { 803 return status; 804 } 805 806 pChannel = m_parent->getChannelByHandle(frame->ch_id); 807 for (int8_t i = 0; i < mPPChannelCount; i++) { 808 if (pChannel == mPPChannels[i]->getSrcChannel()) { 809 m_pReprocChannel = mPPChannels[i]; 810 break; 811 } 812 } 813 814 if ((m_pReprocChannel != NULL) && (pChannel == m_pReprocChannel->getSrcChannel())) { 815 QCameraStream *pStream = NULL; 816 for (uint8_t i = 0; i < m_pReprocChannel->getNumOfStreams(); i++) { 817 pStream = m_pReprocChannel->getStreamByIndex(i); 818 if (pStream && (m_inputPPQ.getCurrentSize() > 0) && 819 (m_ongoingPPQ.getCurrentSize() >= pStream->getNumQueuedBuf())) { 820 LOGW("Out of PP Buffer PPQ = %d ongoingQ = %d Jpeg = %d onJpeg = %d", 821 m_inputPPQ.getCurrentSize(), m_ongoingPPQ.getCurrentSize(), 822 m_inputJpegQ.getCurrentSize(), m_ongoingJpegQ.getCurrentSize()); 823 status = FALSE; 824 break; 825 } 826 } 827 } 828 return status; 829 } 830 831 /*=========================================================================== 832 * FUNCTION : getOfflinePPInputBuffer 833 * 834 * DESCRIPTION: Function to generate offline post proc buffer 835 * 836 * PARAMETERS : 837 * @src_frame : process frame received from mm-camera-interface 838 * 839 * RETURN : Buffer pointer if successfull 840 * : NULL in case of failures 841 *==========================================================================*/ 842 mm_camera_buf_def_t *QCameraPostProcessor::getOfflinePPInputBuffer( 843 mm_camera_super_buf_t *src_frame) 844 { 845 mm_camera_buf_def_t *mBufDefs = NULL; 846 QCameraChannel *pChannel = NULL; 847 QCameraStream *src_pStream = NULL; 848 mm_camera_buf_def_t *data_frame = NULL; 849 mm_camera_buf_def_t *meta_frame = NULL; 850 851 if (mOfflineDataBufs == NULL) { 852 LOGE("Offline Buffer not allocated"); 853 return NULL; 854 } 855 856 uint32_t num_bufs = mOfflineDataBufs->getCnt(); 857 size_t bufDefsSize = num_bufs * sizeof(mm_camera_buf_def_t); 858 mBufDefs = (mm_camera_buf_def_t *)malloc(bufDefsSize); 859 if (mBufDefs == NULL) { 860 LOGE("No memory"); 861 return NULL; 862 } 863 memset(mBufDefs, 0, bufDefsSize); 864 865 pChannel = m_parent->getChannelByHandle(src_frame->ch_id); 866 for (uint32_t i = 0; i < src_frame->num_bufs; i++) { 867 src_pStream = pChannel->getStreamByHandle( 868 src_frame->bufs[i]->stream_id); 869 if (src_pStream != NULL) { 870 if (src_pStream->getMyType() == CAM_STREAM_TYPE_RAW) { 871 LOGH("Found RAW input stream"); 872 data_frame = src_frame->bufs[i]; 873 } else if (src_pStream->getMyType() == CAM_STREAM_TYPE_METADATA){ 874 LOGH("Found Metada input stream"); 875 meta_frame = src_frame->bufs[i]; 876 } 877 } 878 } 879 880 if ((src_pStream != NULL) && (data_frame != NULL)) { 881 cam_frame_len_offset_t offset; 882 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 883 src_pStream->getFrameOffset(offset); 884 for (uint32_t i = 0; i < num_bufs; i++) { 885 mBufDefs[i] = *data_frame; 886 mOfflineDataBufs->getBufDef(offset, mBufDefs[i], i); 887 888 LOGD("Dumping RAW data on offline buffer"); 889 /*Actual data memcpy just for verification*/ 890 memcpy(mBufDefs[i].buffer, data_frame->buffer, 891 mBufDefs[i].frame_len); 892 } 893 releaseSuperBuf(src_frame, CAM_STREAM_TYPE_RAW); 894 } else { 895 free(mBufDefs); 896 mBufDefs = NULL; 897 } 898 899 LOGH("mBufDefs = %p", mBufDefs); 900 return mBufDefs; 901 } 902 903 /*=========================================================================== 904 * FUNCTION : processData 905 * 906 * DESCRIPTION: enqueue data into dataProc thread 907 * 908 * PARAMETERS : 909 * @frame : process frame received from mm-camera-interface 910 * 911 * RETURN : int32_t type of status 912 * NO_ERROR -- success 913 * none-zero failure code 914 * 915 * NOTE : depends on if offline reprocess is needed, received frame will 916 * be sent to either input queue of postprocess or jpeg encoding 917 *==========================================================================*/ 918 int32_t QCameraPostProcessor::processData(mm_camera_super_buf_t *frame) 919 { 920 if (m_bInited == FALSE) { 921 LOGE("postproc not initialized yet"); 922 return UNKNOWN_ERROR; 923 } 924 925 if (frame == NULL) { 926 LOGE("Invalid parameter"); 927 return UNKNOWN_ERROR; 928 } 929 930 mm_camera_buf_def_t *meta_frame = NULL; 931 for (uint32_t i = 0; i < frame->num_bufs; i++) { 932 // look through input superbuf 933 if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 934 meta_frame = frame->bufs[i]; 935 break; 936 } 937 } 938 if (meta_frame != NULL) { 939 //Function to upadte metadata for frame based parameter 940 m_parent->updateMetadata((metadata_buffer_t *)meta_frame->buffer); 941 } 942 943 if (m_parent->needReprocess()) { 944 if ((!m_parent->isLongshotEnabled() && 945 !m_parent->m_stateMachine.isNonZSLCaptureRunning()) || 946 (m_parent->isLongshotEnabled() && 947 m_parent->isCaptureShutterEnabled())) { 948 //play shutter sound 949 m_parent->playShutter(); 950 } 951 952 ATRACE_INT("Camera:Reprocess", 1); 953 LOGH("need reprocess"); 954 955 // enqueu to post proc input queue 956 qcamera_pp_data_t *pp_request_job = 957 (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t)); 958 if (pp_request_job == NULL) { 959 LOGE("No memory for pproc job"); 960 return NO_MEMORY; 961 } 962 memset(pp_request_job, 0, sizeof(qcamera_pp_data_t)); 963 pp_request_job->src_frame = frame; 964 pp_request_job->src_reproc_frame = frame; 965 pp_request_job->reprocCount = 0; 966 pp_request_job->ppChannelIndex = 0; 967 968 if ((NULL != frame) && 969 (0 < frame->num_bufs) 970 && (m_parent->isRegularCapture())) { 971 /*Regular capture. Source stream will be deleted*/ 972 mm_camera_buf_def_t *bufs = NULL; 973 uint32_t num_bufs = frame->num_bufs; 974 bufs = new mm_camera_buf_def_t[num_bufs]; 975 if (NULL == bufs) { 976 LOGE("Unable to allocate cached buffers"); 977 return NO_MEMORY; 978 } 979 980 for (uint32_t i = 0; i < num_bufs; i++) { 981 bufs[i] = *frame->bufs[i]; 982 frame->bufs[i] = &bufs[i]; 983 } 984 pp_request_job->src_reproc_bufs = bufs; 985 986 // Don't release source frame after encoding 987 // at this point the source channel will not exist. 988 pp_request_job->reproc_frame_release = true; 989 } 990 991 if (mOfflineDataBufs != NULL) { 992 pp_request_job->offline_reproc_buf = 993 getOfflinePPInputBuffer(frame); 994 if (pp_request_job->offline_reproc_buf != NULL) { 995 pp_request_job->offline_buffer = true; 996 } 997 } 998 999 if (false == m_inputPPQ.enqueue((void *)pp_request_job)) { 1000 LOGW("Input PP Q is not active!!!"); 1001 releaseSuperBuf(frame); 1002 free(frame); 1003 free(pp_request_job); 1004 frame = NULL; 1005 pp_request_job = NULL; 1006 return NO_ERROR; 1007 } 1008 if (m_parent->mParameters.isAdvCamFeaturesEnabled() 1009 && (meta_frame != NULL)) { 1010 m_InputMetadata.add(meta_frame); 1011 } 1012 } else if (m_parent->mParameters.isNV16PictureFormat() || 1013 m_parent->mParameters.isNV21PictureFormat()) { 1014 //check if raw frame information is needed. 1015 if(m_parent->mParameters.isYUVFrameInfoNeeded()) 1016 setYUVFrameInfo(frame); 1017 1018 processRawData(frame); 1019 } else { 1020 //play shutter sound 1021 if(!m_parent->m_stateMachine.isNonZSLCaptureRunning() && 1022 !m_parent->mLongshotEnabled) 1023 m_parent->playShutter(); 1024 1025 LOGH("no need offline reprocess, sending to jpeg encoding"); 1026 qcamera_jpeg_data_t *jpeg_job = 1027 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t)); 1028 if (jpeg_job == NULL) { 1029 LOGE("No memory for jpeg job"); 1030 return NO_MEMORY; 1031 } 1032 1033 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t)); 1034 jpeg_job->src_frame = frame; 1035 1036 if (meta_frame != NULL) { 1037 // fill in meta data frame ptr 1038 jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer; 1039 } 1040 1041 // enqueu to jpeg input queue 1042 if (!m_inputJpegQ.enqueue((void *)jpeg_job)) { 1043 LOGW("Input Jpeg Q is not active!!!"); 1044 releaseJpegJobData(jpeg_job); 1045 free(jpeg_job); 1046 jpeg_job = NULL; 1047 return NO_ERROR; 1048 } 1049 } 1050 1051 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 1052 return NO_ERROR; 1053 } 1054 1055 /*=========================================================================== 1056 * FUNCTION : processRawData 1057 * 1058 * DESCRIPTION: enqueue raw data into dataProc thread 1059 * 1060 * PARAMETERS : 1061 * @frame : process frame received from mm-camera-interface 1062 * 1063 * RETURN : int32_t type of status 1064 * NO_ERROR -- success 1065 * none-zero failure code 1066 *==========================================================================*/ 1067 int32_t QCameraPostProcessor::processRawData(mm_camera_super_buf_t *frame) 1068 { 1069 if (m_bInited == FALSE) { 1070 LOGE("postproc not initialized yet"); 1071 return UNKNOWN_ERROR; 1072 } 1073 1074 // enqueu to raw input queue 1075 if (m_inputRawQ.enqueue((void *)frame)) { 1076 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 1077 } else { 1078 LOGW("m_inputRawQ is not active!!!"); 1079 releaseSuperBuf(frame); 1080 free(frame); 1081 frame = NULL; 1082 } 1083 return NO_ERROR; 1084 } 1085 1086 /*=========================================================================== 1087 * FUNCTION : processJpegEvt 1088 * 1089 * DESCRIPTION: process jpeg event from mm-jpeg-interface. 1090 * 1091 * PARAMETERS : 1092 * @evt : payload of jpeg event, including information about jpeg encoding 1093 * status, jpeg size and so on. 1094 * 1095 * RETURN : int32_t type of status 1096 * NO_ERROR -- success 1097 * none-zero failure code 1098 * 1099 * NOTE : This event will also trigger DataProc thread to move to next job 1100 * processing (i.e., send a new jpeg encoding job to mm-jpeg-interface 1101 * if there is any pending job in jpeg input queue) 1102 *==========================================================================*/ 1103 int32_t QCameraPostProcessor::processJpegEvt(qcamera_jpeg_evt_payload_t *evt) 1104 { 1105 if (m_bInited == FALSE) { 1106 LOGE("postproc not initialized yet"); 1107 return UNKNOWN_ERROR; 1108 } 1109 1110 int32_t rc = NO_ERROR; 1111 camera_memory_t *jpeg_mem = NULL; 1112 omx_jpeg_ouput_buf_t *jpeg_out = NULL; 1113 void *jpegData = NULL; 1114 if (mUseSaveProc && m_parent->isLongshotEnabled()) { 1115 qcamera_jpeg_evt_payload_t *saveData = ( qcamera_jpeg_evt_payload_t * ) malloc(sizeof(qcamera_jpeg_evt_payload_t)); 1116 if ( NULL == saveData ) { 1117 LOGE("Can not allocate save data message!"); 1118 return NO_MEMORY; 1119 } 1120 *saveData = *evt; 1121 if (m_inputSaveQ.enqueue((void *) saveData)) { 1122 m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 1123 } else { 1124 LOGD("m_inputSaveQ PP Q is not active!!!"); 1125 free(saveData); 1126 saveData = NULL; 1127 return rc; 1128 } 1129 } else { 1130 /* To be removed later when ISP Frame sync feature is available 1131 qcamera_jpeg_data_t *jpeg_job = 1132 (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue(matchJobId, 1133 (void*)&evt->jobId); 1134 uint32_t frame_idx = jpeg_job->src_frame->bufs[0]->frame_idx;*/ 1135 uint32_t frame_idx = 75; 1136 LOGH("FRAME INDEX %d", frame_idx); 1137 // Release jpeg job data 1138 m_ongoingJpegQ.flushNodes(matchJobId, (void*)&evt->jobId); 1139 1140 if (m_inputPPQ.getCurrentSize() > 0) { 1141 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 1142 } 1143 LOGH("[KPI Perf] : jpeg job %d", evt->jobId); 1144 1145 if ((false == m_parent->m_bIntJpegEvtPending) && 1146 (m_parent->mDataCb == NULL || 1147 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) == 0 )) { 1148 LOGW("No dataCB or CAMERA_MSG_COMPRESSED_IMAGE not enabled"); 1149 rc = NO_ERROR; 1150 goto end; 1151 } 1152 1153 if(evt->status == JPEG_JOB_STATUS_ERROR) { 1154 LOGE("Error event handled from jpeg, status = %d", 1155 evt->status); 1156 rc = FAILED_TRANSACTION; 1157 goto end; 1158 } 1159 if (!mJpegMemOpt) { 1160 jpegData = evt->out_data.buf_vaddr; 1161 } 1162 else { 1163 jpeg_out = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr; 1164 if (jpeg_out != NULL) { 1165 jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl; 1166 if (jpeg_mem != NULL) { 1167 jpegData = jpeg_mem->data; 1168 } 1169 } 1170 } 1171 m_parent->dumpJpegToFile(jpegData, 1172 evt->out_data.buf_filled_len, 1173 evt->jobId); 1174 LOGH("Dump jpeg_size=%d", evt->out_data.buf_filled_len); 1175 if(true == m_parent->m_bIntJpegEvtPending) { 1176 //Sending JPEG snapshot taken notification to HAL 1177 pthread_mutex_lock(&m_parent->m_int_lock); 1178 pthread_cond_signal(&m_parent->m_int_cond); 1179 pthread_mutex_unlock(&m_parent->m_int_lock); 1180 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 1181 return rc; 1182 } 1183 if (!mJpegMemOpt) { 1184 // alloc jpeg memory to pass to upper layer 1185 jpeg_mem = m_parent->mGetMemory(-1, evt->out_data.buf_filled_len, 1186 1, m_parent->mCallbackCookie); 1187 if (NULL == jpeg_mem) { 1188 rc = NO_MEMORY; 1189 LOGE("getMemory for jpeg, ret = NO_MEMORY"); 1190 goto end; 1191 } 1192 memcpy(jpeg_mem->data, evt->out_data.buf_vaddr, evt->out_data.buf_filled_len); 1193 } 1194 LOGH("Calling upperlayer callback to store JPEG image"); 1195 qcamera_release_data_t release_data; 1196 memset(&release_data, 0, sizeof(qcamera_release_data_t)); 1197 release_data.data = jpeg_mem; 1198 LOGI("[KPI Perf]: PROFILE_JPEG_CB "); 1199 rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 1200 jpeg_mem, 1201 0, 1202 NULL, 1203 &release_data, 1204 frame_idx); 1205 m_parent->setOutputImageCount(m_parent->getOutputImageCount() + 1); 1206 1207 end: 1208 if (rc != NO_ERROR) { 1209 // send error msg to upper layer 1210 LOGE("Jpeg Encoding failed. Notify Application"); 1211 sendEvtNotify(CAMERA_MSG_ERROR, 1212 UNKNOWN_ERROR, 1213 0); 1214 1215 if (NULL != jpeg_mem) { 1216 jpeg_mem->release(jpeg_mem); 1217 jpeg_mem = NULL; 1218 } 1219 } 1220 1221 /* check whether to send callback for depth map */ 1222 if (m_parent->mParameters.isUbiRefocus() && 1223 (m_parent->getOutputImageCount() + 1 == 1224 m_parent->mParameters.getRefocusOutputCount())) { 1225 m_parent->setOutputImageCount(m_parent->getOutputImageCount() + 1); 1226 1227 jpeg_mem = m_DataMem; 1228 release_data.data = jpeg_mem; 1229 m_DataMem = NULL; 1230 LOGH("[KPI Perf]: send jpeg callback for depthmap "); 1231 rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 1232 jpeg_mem, 1233 0, 1234 NULL, 1235 &release_data, 1236 frame_idx); 1237 if (rc != NO_ERROR) { 1238 // send error msg to upper layer 1239 sendEvtNotify(CAMERA_MSG_ERROR, 1240 UNKNOWN_ERROR, 1241 0); 1242 if (NULL != jpeg_mem) { 1243 jpeg_mem->release(jpeg_mem); 1244 jpeg_mem = NULL; 1245 } 1246 } 1247 m_DataMem = NULL; 1248 } 1249 } 1250 1251 // wait up data proc thread to do next job, 1252 // if previous request is blocked due to ongoing jpeg job 1253 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 1254 1255 return rc; 1256 } 1257 1258 /*=========================================================================== 1259 * FUNCTION : processPPData 1260 * 1261 * DESCRIPTION: process received frame after reprocess. 1262 * 1263 * PARAMETERS : 1264 * @frame : received frame from reprocess channel. 1265 * 1266 * RETURN : int32_t type of status 1267 * NO_ERROR -- success 1268 * none-zero failure code 1269 * 1270 * NOTE : The frame after reprocess need to send to jpeg encoding. 1271 *==========================================================================*/ 1272 int32_t QCameraPostProcessor::processPPData(mm_camera_super_buf_t *frame) 1273 { 1274 bool triggerEvent = TRUE; 1275 1276 LOGD("QCameraPostProcessor::processPPData"); 1277 bool needSuperBufMatch = m_parent->mParameters.generateThumbFromMain(); 1278 if (m_bInited == FALSE) { 1279 LOGE("postproc not initialized yet"); 1280 return UNKNOWN_ERROR; 1281 } 1282 1283 qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue(); 1284 if (NULL == job) { 1285 LOGE("Cannot find reprocess job"); 1286 return BAD_VALUE; 1287 } 1288 1289 if (!needSuperBufMatch && (job->src_frame == NULL 1290 || job->src_reproc_frame == NULL) ) { 1291 LOGE("Invalid reprocess job"); 1292 return BAD_VALUE; 1293 } 1294 1295 if (!needSuperBufMatch && (m_parent->mParameters.isNV16PictureFormat() || 1296 m_parent->mParameters.isNV21PictureFormat())) { 1297 releaseOngoingPPData(job, this); 1298 free(job); 1299 1300 if(m_parent->mParameters.isYUVFrameInfoNeeded()) 1301 setYUVFrameInfo(frame); 1302 return processRawData(frame); 1303 } 1304 #ifdef TARGET_TS_MAKEUP 1305 // find snapshot frame frame 1306 mm_camera_buf_def_t *pReprocFrame = NULL; 1307 QCameraStream * pSnapshotStream = NULL; 1308 QCameraChannel *pChannel = m_parent->getChannelByHandle(frame->ch_id); 1309 if (pChannel == NULL) { 1310 for (int8_t i = 0; i < mPPChannelCount; i++) { 1311 if ((mPPChannels[i] != NULL) && 1312 (validate_handle(mPPChannels[i]->getMyHandle(), frame->ch_id))) { 1313 pChannel = mPPChannels[i]; 1314 break; 1315 } 1316 } 1317 } 1318 if (pChannel == NULL) { 1319 LOGE("No corresponding channel (ch_id = %d) exist, return here", 1320 frame->ch_id); 1321 return BAD_VALUE; 1322 } 1323 1324 for (uint32_t i = 0; i < frame->num_bufs; i++) { 1325 pSnapshotStream = pChannel->getStreamByHandle(frame->bufs[i]->stream_id); 1326 if (pSnapshotStream != NULL) { 1327 if (pSnapshotStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { 1328 pReprocFrame = frame->bufs[i]; 1329 break; 1330 } 1331 } 1332 } 1333 if (pReprocFrame != NULL && m_parent->mParameters.isFaceDetectionEnabled()) { 1334 m_parent->TsMakeupProcess_Snapshot(pReprocFrame,pSnapshotStream); 1335 } else { 1336 LOGH("pReprocFrame == NULL || isFaceDetectionEnabled = %d", 1337 m_parent->mParameters.isFaceDetectionEnabled()); 1338 } 1339 #endif 1340 if ((m_parent->isLongshotEnabled()) 1341 && (!m_parent->isCaptureShutterEnabled()) 1342 && (!m_parent->mCACDoneReceived)) { 1343 // play shutter sound for longshot 1344 // after reprocess is done 1345 m_parent->playShutter(); 1346 } 1347 m_parent->mCACDoneReceived = FALSE; 1348 1349 int8_t mCurReprocCount = job->reprocCount; 1350 int8_t mCurChannelIndex = job->ppChannelIndex; 1351 if ( mCurReprocCount > 1 ) { 1352 //In case of pp 2nd pass, we can release input of 2nd pass 1353 releaseSuperBuf(job->src_frame); 1354 free(job->src_frame); 1355 job->src_frame = NULL; 1356 } 1357 1358 LOGD("mCurReprocCount = %d mCurChannelIndex = %d mTotalNumReproc = %d", 1359 mCurReprocCount, mCurChannelIndex, 1360 m_parent->mParameters.getReprocCount()); 1361 if (mCurReprocCount < m_parent->mParameters.getReprocCount()) { 1362 //More pp pass needed. Push frame back to pp queue. 1363 qcamera_pp_data_t *pp_request_job = job; 1364 pp_request_job->src_frame = frame; 1365 1366 if ((mPPChannels[mCurChannelIndex]->getReprocCount() 1367 == mCurReprocCount) && 1368 (mPPChannels[mCurChannelIndex + 1] != NULL)) { 1369 pp_request_job->ppChannelIndex++; 1370 } 1371 1372 // enqueu to post proc input queue 1373 if (false == m_inputPPQ.enqueue((void *)pp_request_job)) { 1374 LOGW("m_input PP Q is not active!!!"); 1375 releaseOngoingPPData(pp_request_job,this); 1376 free(pp_request_job); 1377 pp_request_job = NULL; 1378 triggerEvent = FALSE; 1379 } 1380 } else { 1381 //Done with post processing. Send frame to Jpeg 1382 qcamera_jpeg_data_t *jpeg_job = 1383 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t)); 1384 if (jpeg_job == NULL) { 1385 LOGE("No memory for jpeg job"); 1386 return NO_MEMORY; 1387 } 1388 1389 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t)); 1390 jpeg_job->src_frame = frame; 1391 jpeg_job->src_reproc_frame = job ? job->src_reproc_frame : NULL; 1392 jpeg_job->src_reproc_bufs = job ? job->src_reproc_bufs : NULL; 1393 jpeg_job->reproc_frame_release = job ? job->reproc_frame_release : false; 1394 jpeg_job->offline_reproc_buf = job ? job->offline_reproc_buf : NULL; 1395 jpeg_job->offline_buffer = job ? job->offline_buffer : false; 1396 1397 // find meta data frame 1398 mm_camera_buf_def_t *meta_frame = NULL; 1399 if (m_parent->mParameters.isAdvCamFeaturesEnabled()) { 1400 size_t meta_idx = m_parent->mParameters.getExifBufIndex(m_PPindex); 1401 if (m_InputMetadata.size() >= (meta_idx + 1)) { 1402 meta_frame = m_InputMetadata.itemAt(meta_idx); 1403 } else { 1404 LOGW("Input metadata vector contains %d entries, index required %d", 1405 m_InputMetadata.size(), meta_idx); 1406 } 1407 m_PPindex++; 1408 } else { 1409 for (uint32_t i = 0; job && job->src_reproc_frame && 1410 (i < job->src_reproc_frame->num_bufs); i++) { 1411 // look through input superbuf 1412 if (job->src_reproc_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 1413 meta_frame = job->src_reproc_frame->bufs[i]; 1414 break; 1415 } 1416 } 1417 1418 if (meta_frame == NULL) { 1419 // look through reprocess superbuf 1420 for (uint32_t i = 0; i < frame->num_bufs; i++) { 1421 if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 1422 meta_frame = frame->bufs[i]; 1423 break; 1424 } 1425 } 1426 } 1427 } 1428 if (meta_frame != NULL) { 1429 // fill in meta data frame ptr 1430 jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer; 1431 } 1432 1433 // enqueu reprocessed frame to jpeg input queue 1434 if (false == m_inputJpegQ.enqueue((void *)jpeg_job)) { 1435 LOGW("Input Jpeg Q is not active!!!"); 1436 releaseJpegJobData(jpeg_job); 1437 free(jpeg_job); 1438 jpeg_job = NULL; 1439 triggerEvent = FALSE; 1440 } 1441 1442 // free pp job buf 1443 pthread_mutex_lock(&m_reprocess_lock); 1444 if (job) { 1445 free(job); 1446 } 1447 pthread_mutex_unlock(&m_reprocess_lock); 1448 } 1449 1450 LOGD(""); 1451 // wait up data proc thread 1452 1453 if (triggerEvent) { 1454 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 1455 } 1456 1457 return NO_ERROR; 1458 } 1459 1460 /*=========================================================================== 1461 * FUNCTION : findJpegJobByJobId 1462 * 1463 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID 1464 * 1465 * PARAMETERS : 1466 * @jobId : job Id of the job 1467 * 1468 * RETURN : ptr to a jpeg job struct. NULL if not found. 1469 * 1470 * NOTE : Currently only one job is sending to mm-jpeg-interface for jpeg 1471 * encoding. Therefore simply dequeue from the ongoing Jpeg Queue 1472 * will serve the purpose to find the jpeg job. 1473 *==========================================================================*/ 1474 qcamera_jpeg_data_t *QCameraPostProcessor::findJpegJobByJobId(uint32_t jobId) 1475 { 1476 qcamera_jpeg_data_t * job = NULL; 1477 if (jobId == 0) { 1478 LOGE("not a valid jpeg jobId"); 1479 return NULL; 1480 } 1481 1482 // currely only one jpeg job ongoing, so simply dequeue the head 1483 job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue(); 1484 return job; 1485 } 1486 1487 /*=========================================================================== 1488 * FUNCTION : releasePPInputData 1489 * 1490 * DESCRIPTION: callback function to release post process input data node 1491 * 1492 * PARAMETERS : 1493 * @data : ptr to post process input data 1494 * @user_data : user data ptr (QCameraReprocessor) 1495 * 1496 * RETURN : None 1497 *==========================================================================*/ 1498 void QCameraPostProcessor::releasePPInputData(void *data, void *user_data) 1499 { 1500 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data; 1501 if (NULL != pme) { 1502 qcamera_pp_request_t *pp_job = (qcamera_pp_request_t *)data; 1503 if (NULL != pp_job->src_frame) { 1504 pme->releaseSuperBuf(pp_job->src_frame); 1505 if (pp_job->src_frame == pp_job->src_reproc_frame) 1506 pp_job->src_reproc_frame = NULL; 1507 free(pp_job->src_frame); 1508 pp_job->src_frame = NULL; 1509 } 1510 if (NULL != pp_job->src_reproc_frame) { 1511 pme->releaseSuperBuf(pp_job->src_reproc_frame); 1512 free(pp_job->src_reproc_frame); 1513 pp_job->src_reproc_frame = NULL; 1514 } 1515 pp_job->reprocCount = 0; 1516 } 1517 } 1518 1519 /*=========================================================================== 1520 * FUNCTION : releaseJpegData 1521 * 1522 * DESCRIPTION: callback function to release jpeg job node 1523 * 1524 * PARAMETERS : 1525 * @data : ptr to ongoing jpeg job data 1526 * @user_data : user data ptr (QCameraReprocessor) 1527 * 1528 * RETURN : None 1529 *==========================================================================*/ 1530 void QCameraPostProcessor::releaseJpegData(void *data, void *user_data) 1531 { 1532 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data; 1533 if (NULL != pme) { 1534 pme->releaseJpegJobData((qcamera_jpeg_data_t *)data); 1535 LOGH("Rleased job ID %u", 1536 ((qcamera_jpeg_data_t *)data)->jobId); 1537 } 1538 } 1539 1540 /*=========================================================================== 1541 * FUNCTION : releaseOngoingPPData 1542 * 1543 * DESCRIPTION: callback function to release ongoing postprocess job node 1544 * 1545 * PARAMETERS : 1546 * @data : ptr to onging postprocess job 1547 * @user_data : user data ptr (QCameraReprocessor) 1548 * 1549 * RETURN : None 1550 *==========================================================================*/ 1551 void QCameraPostProcessor::releaseOngoingPPData(void *data, void *user_data) 1552 { 1553 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data; 1554 if (NULL != pme) { 1555 qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data; 1556 if (NULL != pp_job->src_frame) { 1557 if (!pp_job->reproc_frame_release) { 1558 pme->releaseSuperBuf(pp_job->src_frame); 1559 } 1560 if (pp_job->src_frame == pp_job->src_reproc_frame) 1561 pp_job->src_reproc_frame = NULL; 1562 1563 free(pp_job->src_frame); 1564 pp_job->src_frame = NULL; 1565 } 1566 if (NULL != pp_job->src_reproc_frame) { 1567 pme->releaseSuperBuf(pp_job->src_reproc_frame); 1568 free(pp_job->src_reproc_frame); 1569 pp_job->src_reproc_frame = NULL; 1570 } 1571 if ((pp_job->offline_reproc_buf != NULL) 1572 && (pp_job->offline_buffer)) { 1573 free(pp_job->offline_reproc_buf); 1574 pp_job->offline_buffer = false; 1575 } 1576 pp_job->reprocCount = 0; 1577 } 1578 } 1579 1580 /*=========================================================================== 1581 * FUNCTION : releaseNotifyData 1582 * 1583 * DESCRIPTION: function to release internal resources in notify data struct 1584 * 1585 * PARAMETERS : 1586 * @user_data : ptr user data 1587 * @cookie : callback cookie 1588 * @cb_status : callback status 1589 * 1590 * RETURN : None 1591 * 1592 * NOTE : deallocate jpeg heap memory if it's not NULL 1593 *==========================================================================*/ 1594 void QCameraPostProcessor::releaseNotifyData(void *user_data, 1595 void *cookie, 1596 int32_t cb_status) 1597 { 1598 LOGD("releaseNotifyData release_data %p", user_data); 1599 1600 qcamera_data_argm_t *app_cb = ( qcamera_data_argm_t * ) user_data; 1601 QCameraPostProcessor *postProc = ( QCameraPostProcessor * ) cookie; 1602 if ( ( NULL != app_cb ) && ( NULL != postProc ) ) { 1603 1604 if ( postProc->mUseSaveProc && 1605 app_cb->release_data.unlinkFile && 1606 ( NO_ERROR != cb_status ) ) { 1607 1608 String8 unlinkPath((const char *) app_cb->release_data.data->data, 1609 app_cb->release_data.data->size); 1610 int rc = unlink(unlinkPath.string()); 1611 LOGH("Unlinking stored file rc = %d", 1612 rc); 1613 } 1614 1615 if (app_cb && NULL != app_cb->release_data.data) { 1616 app_cb->release_data.data->release(app_cb->release_data.data); 1617 app_cb->release_data.data = NULL; 1618 } 1619 if (app_cb && NULL != app_cb->release_data.frame) { 1620 postProc->releaseSuperBuf(app_cb->release_data.frame); 1621 free(app_cb->release_data.frame); 1622 app_cb->release_data.frame = NULL; 1623 } 1624 if (app_cb && NULL != app_cb->release_data.streamBufs) { 1625 app_cb->release_data.streamBufs->deallocate(); 1626 delete app_cb->release_data.streamBufs; 1627 app_cb->release_data.streamBufs = NULL; 1628 } 1629 free(app_cb); 1630 } 1631 } 1632 1633 /*=========================================================================== 1634 * FUNCTION : releaseSuperBuf 1635 * 1636 * DESCRIPTION: function to release a superbuf frame by returning back to kernel 1637 * 1638 * PARAMETERS : 1639 * @super_buf : ptr to the superbuf frame 1640 * 1641 * RETURN : None 1642 *==========================================================================*/ 1643 void QCameraPostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf) 1644 { 1645 QCameraChannel *pChannel = NULL; 1646 1647 if (NULL != super_buf) { 1648 pChannel = m_parent->getChannelByHandle(super_buf->ch_id); 1649 1650 if ( NULL == pChannel ) { 1651 for (int8_t i = 0; i < mPPChannelCount; i++) { 1652 if ((mPPChannels[i] != NULL) && 1653 (validate_handle(mPPChannels[i]->getMyHandle(), 1654 super_buf->ch_id))) { 1655 pChannel = mPPChannels[i]; 1656 break; 1657 } 1658 } 1659 } 1660 1661 if (pChannel != NULL) { 1662 pChannel->bufDone(super_buf); 1663 } else { 1664 LOGE("Channel id %d not found!!", 1665 super_buf->ch_id); 1666 } 1667 } 1668 } 1669 1670 /*=========================================================================== 1671 * FUNCTION : releaseSuperBuf 1672 * 1673 * DESCRIPTION : function to release a superbuf frame by returning back to kernel 1674 * 1675 * PARAMETERS : 1676 * @super_buf : ptr to the superbuf frame 1677 * @stream_type: Type of stream to be released 1678 * 1679 * RETURN : None 1680 *==========================================================================*/ 1681 void QCameraPostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf, 1682 cam_stream_type_t stream_type) 1683 { 1684 QCameraChannel *pChannel = NULL; 1685 1686 if (NULL != super_buf) { 1687 pChannel = m_parent->getChannelByHandle(super_buf->ch_id); 1688 if (pChannel == NULL) { 1689 for (int8_t i = 0; i < mPPChannelCount; i++) { 1690 if ((mPPChannels[i] != NULL) && 1691 (validate_handle(mPPChannels[i]->getMyHandle(), 1692 super_buf->ch_id))) { 1693 pChannel = mPPChannels[i]; 1694 break; 1695 } 1696 } 1697 } 1698 1699 if (pChannel != NULL) { 1700 for (uint32_t i = 0; i < super_buf->num_bufs; i++) { 1701 if (super_buf->bufs[i] != NULL) { 1702 QCameraStream *pStream = 1703 pChannel->getStreamByHandle(super_buf->bufs[i]->stream_id); 1704 if ((pStream != NULL) && ((pStream->getMyType() == stream_type) 1705 || (pStream->getMyOriginalType() == stream_type))) { 1706 pChannel->bufDone(super_buf, super_buf->bufs[i]->stream_id); 1707 break; 1708 } 1709 } 1710 } 1711 } else { 1712 LOGE("Channel id %d not found!!", 1713 super_buf->ch_id); 1714 } 1715 } 1716 } 1717 1718 /*=========================================================================== 1719 * FUNCTION : releaseJpegJobData 1720 * 1721 * DESCRIPTION: function to release internal resources in jpeg job struct 1722 * 1723 * PARAMETERS : 1724 * @job : ptr to jpeg job struct 1725 * 1726 * RETURN : None 1727 * 1728 * NOTE : original source frame need to be queued back to kernel for 1729 * future use. Output buf of jpeg job need to be released since 1730 * it's allocated for each job. Exif object need to be deleted. 1731 *==========================================================================*/ 1732 void QCameraPostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job) 1733 { 1734 LOGD("E"); 1735 if (NULL != job) { 1736 if (NULL != job->src_reproc_frame) { 1737 if (!job->reproc_frame_release) { 1738 releaseSuperBuf(job->src_reproc_frame); 1739 } 1740 free(job->src_reproc_frame); 1741 job->src_reproc_frame = NULL; 1742 } 1743 1744 if (NULL != job->src_frame) { 1745 releaseSuperBuf(job->src_frame); 1746 free(job->src_frame); 1747 job->src_frame = NULL; 1748 } 1749 1750 if (NULL != job->pJpegExifObj) { 1751 delete job->pJpegExifObj; 1752 job->pJpegExifObj = NULL; 1753 } 1754 1755 if (NULL != job->src_reproc_bufs) { 1756 delete [] job->src_reproc_bufs; 1757 } 1758 1759 if ((job->offline_reproc_buf != NULL) 1760 && (job->offline_buffer)) { 1761 free(job->offline_reproc_buf); 1762 job->offline_buffer = false; 1763 } 1764 } 1765 LOGD("X"); 1766 } 1767 1768 /*=========================================================================== 1769 * FUNCTION : releaseSaveJobData 1770 * 1771 * DESCRIPTION: function to release internal resources in store jobs 1772 * 1773 * PARAMETERS : 1774 * @job : ptr to save job struct 1775 * 1776 * RETURN : None 1777 * 1778 *==========================================================================*/ 1779 void QCameraPostProcessor::releaseSaveJobData(void *data, void *user_data) 1780 { 1781 LOGD("E"); 1782 1783 QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data; 1784 if (NULL == pme) { 1785 LOGE("Invalid postproc handle"); 1786 return; 1787 } 1788 1789 qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) data; 1790 if (job_data == NULL) { 1791 LOGE("Invalid jpeg event data"); 1792 return; 1793 } 1794 1795 // find job by jobId 1796 qcamera_jpeg_data_t *job = pme->findJpegJobByJobId(job_data->jobId); 1797 1798 if (NULL != job) { 1799 pme->releaseJpegJobData(job); 1800 free(job); 1801 } else { 1802 LOGE("Invalid jpeg job"); 1803 } 1804 1805 LOGD("X"); 1806 } 1807 1808 /*=========================================================================== 1809 * FUNCTION : releaseRawData 1810 * 1811 * DESCRIPTION: function to release internal resources in store jobs 1812 * 1813 * PARAMETERS : 1814 * @job : ptr to save job struct 1815 * 1816 * RETURN : None 1817 * 1818 *==========================================================================*/ 1819 void QCameraPostProcessor::releaseRawData(void *data, void *user_data) 1820 { 1821 LOGD("E"); 1822 1823 QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data; 1824 if (NULL == pme) { 1825 LOGE("Invalid postproc handle"); 1826 return; 1827 } 1828 mm_camera_super_buf_t *super_buf = (mm_camera_super_buf_t *) data; 1829 pme->releaseSuperBuf(super_buf); 1830 1831 LOGD("X"); 1832 } 1833 1834 1835 /*=========================================================================== 1836 * FUNCTION : getColorfmtFromImgFmt 1837 * 1838 * DESCRIPTION: function to return jpeg color format based on its image format 1839 * 1840 * PARAMETERS : 1841 * @img_fmt : image format 1842 * 1843 * RETURN : jpeg color format that can be understandable by omx lib 1844 *==========================================================================*/ 1845 mm_jpeg_color_format QCameraPostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt) 1846 { 1847 switch (img_fmt) { 1848 case CAM_FORMAT_YUV_420_NV21: 1849 case CAM_FORMAT_YUV_420_NV21_VENUS: 1850 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 1851 case CAM_FORMAT_YUV_420_NV21_ADRENO: 1852 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 1853 case CAM_FORMAT_YUV_420_NV12: 1854 case CAM_FORMAT_YUV_420_NV12_VENUS: 1855 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 1856 case CAM_FORMAT_YUV_420_YV12: 1857 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 1858 case CAM_FORMAT_YUV_422_NV61: 1859 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1; 1860 case CAM_FORMAT_YUV_422_NV16: 1861 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1; 1862 default: 1863 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 1864 } 1865 } 1866 1867 /*=========================================================================== 1868 * FUNCTION : getJpegImgTypeFromImgFmt 1869 * 1870 * DESCRIPTION: function to return jpeg encode image type based on its image format 1871 * 1872 * PARAMETERS : 1873 * @img_fmt : image format 1874 * 1875 * RETURN : return jpeg source image format (YUV or Bitstream) 1876 *==========================================================================*/ 1877 mm_jpeg_format_t QCameraPostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt) 1878 { 1879 switch (img_fmt) { 1880 case CAM_FORMAT_YUV_420_NV21: 1881 case CAM_FORMAT_YUV_420_NV21_ADRENO: 1882 case CAM_FORMAT_YUV_420_NV12: 1883 case CAM_FORMAT_YUV_420_NV12_VENUS: 1884 case CAM_FORMAT_YUV_420_NV21_VENUS: 1885 case CAM_FORMAT_YUV_420_YV12: 1886 case CAM_FORMAT_YUV_422_NV61: 1887 case CAM_FORMAT_YUV_422_NV16: 1888 return MM_JPEG_FMT_YUV; 1889 default: 1890 return MM_JPEG_FMT_YUV; 1891 } 1892 } 1893 1894 /*=========================================================================== 1895 * FUNCTION : queryStreams 1896 * 1897 * DESCRIPTION: utility method for retrieving main, thumbnail and reprocess 1898 * streams and frame from bundled super buffer 1899 * 1900 * PARAMETERS : 1901 * @main : ptr to main stream if present 1902 * @thumb : ptr to thumbnail stream if present 1903 * @reproc : ptr to reprocess stream if present 1904 * @main_image : ptr to main image if present 1905 * @thumb_image: ptr to thumbnail image if present 1906 * @frame : bundled super buffer 1907 * @reproc_frame : bundled source frame buffer 1908 * 1909 * RETURN : int32_t type of status 1910 * NO_ERROR -- success 1911 * none-zero failure code 1912 *==========================================================================*/ 1913 int32_t QCameraPostProcessor::queryStreams(QCameraStream **main, 1914 QCameraStream **thumb, 1915 QCameraStream **reproc, 1916 mm_camera_buf_def_t **main_image, 1917 mm_camera_buf_def_t **thumb_image, 1918 mm_camera_super_buf_t *frame, 1919 mm_camera_super_buf_t *reproc_frame) 1920 { 1921 if (NULL == frame) { 1922 return NO_INIT; 1923 } 1924 1925 QCameraChannel *pChannel = m_parent->getChannelByHandle(frame->ch_id); 1926 // check reprocess channel if not found 1927 if (pChannel == NULL) { 1928 for (int8_t i = 0; i < mPPChannelCount; i++) { 1929 if ((mPPChannels[i] != NULL) && 1930 validate_handle(mPPChannels[i]->getMyHandle(), frame->ch_id)) { 1931 pChannel = mPPChannels[i]; 1932 break; 1933 } 1934 } 1935 } 1936 if (pChannel == NULL) { 1937 LOGD("No corresponding channel (ch_id = %d) exist, return here", 1938 frame->ch_id); 1939 return BAD_VALUE; 1940 } 1941 1942 // Use snapshot stream to create thumbnail if snapshot and preview 1943 // flip settings doesn't match in ZSL mode. 1944 bool thumb_stream_needed = ((!m_parent->isZSLMode() || 1945 (m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT) == 1946 m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_PREVIEW))) && 1947 !m_parent->mParameters.generateThumbFromMain()); 1948 1949 *main = *thumb = *reproc = NULL; 1950 *main_image = *thumb_image = NULL; 1951 // find snapshot frame and thumnail frame 1952 for (uint32_t i = 0; i < frame->num_bufs; i++) { 1953 QCameraStream *pStream = 1954 pChannel->getStreamByHandle(frame->bufs[i]->stream_id); 1955 if (pStream != NULL) { 1956 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 1957 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 1958 pStream->isTypeOf(CAM_STREAM_TYPE_VIDEO) || 1959 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_VIDEO) || 1960 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)) { 1961 *main= pStream; 1962 *main_image = frame->bufs[i]; 1963 } else if (thumb_stream_needed && 1964 (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 1965 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 1966 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) || 1967 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW))) { 1968 *thumb = pStream; 1969 *thumb_image = frame->bufs[i]; 1970 } 1971 if (pStream->isTypeOf(CAM_STREAM_TYPE_OFFLINE_PROC) ) { 1972 *reproc = pStream; 1973 } 1974 } 1975 } 1976 1977 if (thumb_stream_needed && *thumb_image == NULL && reproc_frame != NULL) { 1978 QCameraChannel *pSrcReprocChannel = NULL; 1979 pSrcReprocChannel = m_parent->getChannelByHandle(reproc_frame->ch_id); 1980 if (pSrcReprocChannel != NULL) { 1981 // find thumbnail frame 1982 for (uint32_t i = 0; i < reproc_frame->num_bufs; i++) { 1983 QCameraStream *pStream = 1984 pSrcReprocChannel->getStreamByHandle( 1985 reproc_frame->bufs[i]->stream_id); 1986 if (pStream != NULL) { 1987 if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 1988 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW)) { 1989 *thumb = pStream; 1990 *thumb_image = reproc_frame->bufs[i]; 1991 } 1992 } 1993 } 1994 } 1995 } 1996 1997 return NO_ERROR; 1998 } 1999 2000 /*=========================================================================== 2001 * FUNCTION : syncStreamParams 2002 * 2003 * DESCRIPTION: Query the runtime parameters of all streams included 2004 * in the main and reprocessed frames 2005 * 2006 * PARAMETERS : 2007 * @frame : Main image super buffer 2008 * @reproc_frame : Image supper buffer that got processed 2009 * 2010 * RETURN : int32_t type of status 2011 * NO_ERROR -- success 2012 * none-zero failure code 2013 *==========================================================================*/ 2014 int32_t QCameraPostProcessor::syncStreamParams(mm_camera_super_buf_t *frame, 2015 mm_camera_super_buf_t *reproc_frame) 2016 { 2017 QCameraStream *reproc_stream = NULL; 2018 QCameraStream *main_stream = NULL; 2019 QCameraStream *thumb_stream = NULL; 2020 mm_camera_buf_def_t *main_frame = NULL; 2021 mm_camera_buf_def_t *thumb_frame = NULL; 2022 int32_t ret = NO_ERROR; 2023 2024 ret = queryStreams(&main_stream, 2025 &thumb_stream, 2026 &reproc_stream, 2027 &main_frame, 2028 &thumb_frame, 2029 frame, 2030 reproc_frame); 2031 if (NO_ERROR != ret) { 2032 LOGE("Camera streams query from input frames failed %d", 2033 ret); 2034 return ret; 2035 } 2036 2037 if (NULL != main_stream) { 2038 ret = main_stream->syncRuntimeParams(); 2039 if (NO_ERROR != ret) { 2040 LOGE("Syncing of main stream runtime parameters failed %d", 2041 ret); 2042 return ret; 2043 } 2044 } 2045 2046 if (NULL != thumb_stream) { 2047 ret = thumb_stream->syncRuntimeParams(); 2048 if (NO_ERROR != ret) { 2049 LOGE("Syncing of thumb stream runtime parameters failed %d", 2050 ret); 2051 return ret; 2052 } 2053 } 2054 2055 if ((NULL != reproc_stream) && (reproc_stream != main_stream)) { 2056 ret = reproc_stream->syncRuntimeParams(); 2057 if (NO_ERROR != ret) { 2058 LOGE("Syncing of reproc stream runtime parameters failed %d", 2059 ret); 2060 return ret; 2061 } 2062 } 2063 2064 return ret; 2065 } 2066 2067 /*=========================================================================== 2068 * FUNCTION : encodeData 2069 * 2070 * DESCRIPTION: function to prepare encoding job information and send to 2071 * mm-jpeg-interface to do the encoding job 2072 * 2073 * PARAMETERS : 2074 * @jpeg_job_data : ptr to a struct saving job related information 2075 * @needNewSess : flag to indicate if a new jpeg encoding session need 2076 * to be created. After creation, this flag will be toggled 2077 * 2078 * RETURN : int32_t type of status 2079 * NO_ERROR -- success 2080 * none-zero failure code 2081 *==========================================================================*/ 2082 int32_t QCameraPostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data, 2083 uint8_t &needNewSess) 2084 { 2085 LOGD("E"); 2086 int32_t ret = NO_ERROR; 2087 mm_jpeg_job_t jpg_job; 2088 uint32_t jobId = 0; 2089 QCameraStream *reproc_stream = NULL; 2090 QCameraStream *main_stream = NULL; 2091 mm_camera_buf_def_t *main_frame = NULL; 2092 QCameraStream *thumb_stream = NULL; 2093 mm_camera_buf_def_t *thumb_frame = NULL; 2094 mm_camera_super_buf_t *recvd_frame = jpeg_job_data->src_frame; 2095 cam_rect_t crop; 2096 cam_stream_parm_buffer_t param; 2097 cam_stream_img_prop_t imgProp; 2098 2099 // find channel 2100 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id); 2101 // check reprocess channel if not found 2102 if (pChannel == NULL) { 2103 for (int8_t i = 0; i < mPPChannelCount; i++) { 2104 if ((mPPChannels[i] != NULL) && 2105 (validate_handle(mPPChannels[i]->getMyHandle(), recvd_frame->ch_id))) { 2106 pChannel = mPPChannels[i]; 2107 break; 2108 } 2109 } 2110 } 2111 2112 if (pChannel == NULL) { 2113 LOGE("No corresponding channel (ch_id = %d) exist, return here", 2114 recvd_frame->ch_id); 2115 return BAD_VALUE; 2116 } 2117 2118 const uint32_t jpeg_rotation = m_parent->mParameters.getJpegRotation(); 2119 2120 ret = queryStreams(&main_stream, 2121 &thumb_stream, 2122 &reproc_stream, 2123 &main_frame, 2124 &thumb_frame, 2125 recvd_frame, 2126 jpeg_job_data->src_reproc_frame); 2127 if (NO_ERROR != ret) { 2128 return ret; 2129 } 2130 2131 if(NULL == main_frame){ 2132 LOGE("Main frame is NULL"); 2133 return BAD_VALUE; 2134 } 2135 2136 if(NULL == thumb_frame){ 2137 LOGD("Thumbnail frame does not exist"); 2138 } 2139 2140 QCameraMemory *memObj = (QCameraMemory *)main_frame->mem_info; 2141 if (NULL == memObj) { 2142 LOGE("Memeory Obj of main frame is NULL"); 2143 return NO_MEMORY; 2144 } 2145 2146 // dump snapshot frame if enabled 2147 m_parent->dumpFrameToFile(main_stream, main_frame, 2148 QCAMERA_DUMP_FRM_INPUT_JPEG, (char *)"CPP"); 2149 2150 // send upperlayer callback for raw image 2151 camera_memory_t *mem = memObj->getMemory(main_frame->buf_idx, false); 2152 if (NULL != m_parent->mDataCb && 2153 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) { 2154 qcamera_callback_argm_t cbArg; 2155 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 2156 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 2157 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE; 2158 cbArg.data = mem; 2159 cbArg.index = 0; 2160 m_parent->m_cbNotifier.notifyCallback(cbArg); 2161 } 2162 if (NULL != m_parent->mNotifyCb && 2163 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) { 2164 qcamera_callback_argm_t cbArg; 2165 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 2166 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; 2167 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY; 2168 cbArg.ext1 = 0; 2169 cbArg.ext2 = 0; 2170 m_parent->m_cbNotifier.notifyCallback(cbArg); 2171 } 2172 2173 if (mJpegClientHandle <= 0) { 2174 LOGE("Error: bug here, mJpegClientHandle is 0"); 2175 return UNKNOWN_ERROR; 2176 } 2177 2178 if (needNewSess) { 2179 // create jpeg encoding session 2180 mm_jpeg_encode_params_t encodeParam; 2181 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t)); 2182 ret = getJpegEncodingConfig(encodeParam, main_stream, thumb_stream); 2183 if (ret != NO_ERROR) { 2184 LOGE("error getting encoding config"); 2185 return ret; 2186 } 2187 LOGH("[KPI Perf] : call jpeg create_session"); 2188 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId); 2189 if (ret != NO_ERROR) { 2190 LOGE("error creating a new jpeg encoding session"); 2191 return ret; 2192 } 2193 needNewSess = FALSE; 2194 } 2195 // Fill in new job 2196 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t)); 2197 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE; 2198 jpg_job.encode_job.session_id = mJpegSessionId; 2199 jpg_job.encode_job.src_index = (int32_t)main_frame->buf_idx; 2200 jpg_job.encode_job.dst_index = 0; 2201 2202 if (mJpegMemOpt) { 2203 jpg_job.encode_job.dst_index = jpg_job.encode_job.src_index; 2204 } else if (mUseJpegBurst) { 2205 jpg_job.encode_job.dst_index = -1; 2206 } 2207 2208 // use src to reproc frame as work buffer; if src buf is not available 2209 // jpeg interface will allocate work buffer 2210 if (jpeg_job_data->src_reproc_frame != NULL) { 2211 int32_t ret = NO_ERROR; 2212 QCameraStream *main_stream = NULL; 2213 mm_camera_buf_def_t *main_frame = NULL; 2214 QCameraStream *thumb_stream = NULL; 2215 mm_camera_buf_def_t *thumb_frame = NULL; 2216 QCameraStream *reproc_stream = NULL; 2217 mm_camera_buf_def_t *workBuf = NULL; 2218 // Call queryStreams to fetch source of reproc frame 2219 ret = queryStreams(&main_stream, 2220 &thumb_stream, 2221 &reproc_stream, 2222 &main_frame, 2223 &thumb_frame, 2224 jpeg_job_data->src_reproc_frame, 2225 NULL); 2226 2227 if ((NO_ERROR == ret) && ((workBuf = main_frame) != NULL) 2228 && !m_parent->isLowPowerMode()) { 2229 camera_memory_t *camWorkMem = NULL; 2230 int workBufIndex = workBuf->buf_idx; 2231 QCameraMemory *workMem = (QCameraMemory *)workBuf->mem_info; 2232 if (workMem != NULL) { 2233 camWorkMem = workMem->getMemory(workBufIndex, false); 2234 } 2235 if (camWorkMem != NULL && workMem != NULL) { 2236 jpg_job.encode_job.work_buf.buf_size = camWorkMem->size; 2237 jpg_job.encode_job.work_buf.buf_vaddr = (uint8_t *)camWorkMem->data; 2238 jpg_job.encode_job.work_buf.fd = workMem->getFd(workBufIndex); 2239 workMem->invalidateCache(workBufIndex); 2240 } 2241 } 2242 } 2243 2244 cam_dimension_t src_dim; 2245 memset(&src_dim, 0, sizeof(cam_dimension_t)); 2246 main_stream->getFrameDimension(src_dim); 2247 2248 bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled(); 2249 bool img_feature_enabled = 2250 m_parent->mParameters.isUbiFocusEnabled() || 2251 m_parent->mParameters.isUbiRefocus() || 2252 m_parent->mParameters.isChromaFlashEnabled() || 2253 m_parent->mParameters.isOptiZoomEnabled() || 2254 m_parent->mParameters.isStillMoreEnabled(); 2255 2256 LOGH("Crop needed %d", img_feature_enabled); 2257 crop.left = 0; 2258 crop.top = 0; 2259 crop.height = src_dim.height; 2260 crop.width = src_dim.width; 2261 2262 param = main_stream->getOutputCrop(); 2263 for (int i = 0; i < param.outputCrop.num_of_streams; i++) { 2264 if (param.outputCrop.crop_info[i].stream_id 2265 == main_stream->getMyServerID()) { 2266 crop = param.outputCrop.crop_info[i].crop; 2267 main_stream->setCropInfo(crop); 2268 } 2269 } 2270 if (img_feature_enabled) { 2271 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 2272 2273 param = main_stream->getImgProp(); 2274 imgProp = param.imgProp; 2275 main_stream->setCropInfo(imgProp.crop); 2276 crop = imgProp.crop; 2277 thumb_stream = NULL; /* use thumbnail from main image */ 2278 2279 if ((reproc_stream != NULL) && (m_DataMem == NULL) && 2280 m_parent->mParameters.isUbiRefocus()) { 2281 2282 QCameraHeapMemory* miscBufHandler = reproc_stream->getMiscBuf(); 2283 cam_misc_buf_t* refocusResult = 2284 reinterpret_cast<cam_misc_buf_t *>(miscBufHandler->getPtr(0)); 2285 uint32_t resultSize = refocusResult->header_size + 2286 refocusResult->width * refocusResult->height; 2287 camera_memory_t *dataMem = m_parent->mGetMemory(-1, resultSize, 2288 1, m_parent->mCallbackCookie); 2289 2290 LOGH("Refocus result header %u dims %dx%d", 2291 resultSize, refocusResult->width, refocusResult->height); 2292 2293 if (dataMem && dataMem->data) { 2294 memcpy(dataMem->data, refocusResult->data, resultSize); 2295 //save mem pointer for depth map 2296 m_DataMem = dataMem; 2297 } 2298 } 2299 } else if ((reproc_stream != NULL) && (m_parent->mParameters.isTruePortraitEnabled())) { 2300 2301 QCameraHeapMemory* miscBufHandler = reproc_stream->getMiscBuf(); 2302 cam_misc_buf_t* tpResult = 2303 reinterpret_cast<cam_misc_buf_t *>(miscBufHandler->getPtr(0)); 2304 uint32_t tpMetaSize = tpResult->header_size + tpResult->width * tpResult->height; 2305 2306 LOGH("True portrait result header %d% dims dx%d", 2307 tpMetaSize, tpResult->width, tpResult->height); 2308 2309 CAM_DUMP_TO_FILE(QCAMERA_DUMP_FRM_LOCATION"tp", "bm", -1, "y", 2310 &tpResult->data, tpMetaSize); 2311 } 2312 2313 cam_dimension_t dst_dim; 2314 2315 if (hdr_output_crop && crop.height) { 2316 dst_dim.height = crop.height; 2317 } else { 2318 dst_dim.height = src_dim.height; 2319 } 2320 if (hdr_output_crop && crop.width) { 2321 dst_dim.width = crop.width; 2322 } else { 2323 dst_dim.width = src_dim.width; 2324 } 2325 2326 // main dim 2327 jpg_job.encode_job.main_dim.src_dim = src_dim; 2328 jpg_job.encode_job.main_dim.dst_dim = dst_dim; 2329 jpg_job.encode_job.main_dim.crop = crop; 2330 2331 // get 3a sw version info 2332 cam_q3a_version_t sw_version = 2333 m_parent->getCamHalCapabilities()->q3a_version; 2334 2335 // get exif data 2336 QCameraExif *pJpegExifObj = m_parent->getExifData(); 2337 jpeg_job_data->pJpegExifObj = pJpegExifObj; 2338 if (pJpegExifObj != NULL) { 2339 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries(); 2340 jpg_job.encode_job.exif_info.numOfEntries = 2341 pJpegExifObj->getNumOfEntries(); 2342 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] = 2343 sw_version.major_version; 2344 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] = 2345 sw_version.minor_version; 2346 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] = 2347 sw_version.patch_version; 2348 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] = 2349 sw_version.new_feature_des; 2350 } 2351 2352 // set rotation only when no online rotation or offline pp rotation is done before 2353 if (!m_parent->needRotationReprocess()) { 2354 jpg_job.encode_job.rotation = jpeg_rotation; 2355 } 2356 LOGH("jpeg rotation is set to %d", jpg_job.encode_job.rotation); 2357 2358 // thumbnail dim 2359 if (m_bThumbnailNeeded == TRUE) { 2360 m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim); 2361 2362 if (thumb_stream == NULL) { 2363 // need jpeg thumbnail, but no postview/preview stream exists 2364 // we use the main stream/frame to encode thumbnail 2365 thumb_stream = main_stream; 2366 thumb_frame = main_frame; 2367 } 2368 if (m_parent->needRotationReprocess() && 2369 ((90 == jpeg_rotation) || (270 == jpeg_rotation))) { 2370 // swap thumbnail dimensions 2371 cam_dimension_t tmp_dim = jpg_job.encode_job.thumb_dim.dst_dim; 2372 jpg_job.encode_job.thumb_dim.dst_dim.width = tmp_dim.height; 2373 jpg_job.encode_job.thumb_dim.dst_dim.height = tmp_dim.width; 2374 } 2375 2376 memset(&src_dim, 0, sizeof(cam_dimension_t)); 2377 thumb_stream->getFrameDimension(src_dim); 2378 jpg_job.encode_job.thumb_dim.src_dim = src_dim; 2379 2380 // crop is the same if frame is the same 2381 if (thumb_frame != main_frame) { 2382 crop.left = 0; 2383 crop.top = 0; 2384 crop.height = src_dim.height; 2385 crop.width = src_dim.width; 2386 2387 param = thumb_stream->getOutputCrop(); 2388 for (int i = 0; i < param.outputCrop.num_of_streams; i++) { 2389 if (param.outputCrop.crop_info[i].stream_id 2390 == thumb_stream->getMyServerID()) { 2391 crop = param.outputCrop.crop_info[i].crop; 2392 thumb_stream->setCropInfo(crop); 2393 } 2394 } 2395 } 2396 2397 2398 jpg_job.encode_job.thumb_dim.crop = crop; 2399 if (thumb_frame != NULL) { 2400 jpg_job.encode_job.thumb_index = thumb_frame->buf_idx; 2401 } 2402 LOGI("Thumbnail idx = %d src w/h (%dx%d), dst w/h (%dx%d)", 2403 jpg_job.encode_job.thumb_index, 2404 jpg_job.encode_job.thumb_dim.src_dim.width, 2405 jpg_job.encode_job.thumb_dim.src_dim.height, 2406 jpg_job.encode_job.thumb_dim.dst_dim.width, 2407 jpg_job.encode_job.thumb_dim.dst_dim.height); 2408 } 2409 2410 LOGI("Main image idx = %d src w/h (%dx%d), dst w/h (%dx%d)", 2411 jpg_job.encode_job.src_index, 2412 jpg_job.encode_job.main_dim.src_dim.width, 2413 jpg_job.encode_job.main_dim.src_dim.height, 2414 jpg_job.encode_job.main_dim.dst_dim.width, 2415 jpg_job.encode_job.main_dim.dst_dim.height); 2416 2417 if (thumb_frame != NULL) { 2418 // dump thumbnail frame if enabled 2419 m_parent->dumpFrameToFile(thumb_stream, thumb_frame, QCAMERA_DUMP_FRM_THUMBNAIL); 2420 } 2421 2422 if (jpeg_job_data->metadata != NULL) { 2423 // fill in meta data frame ptr 2424 jpg_job.encode_job.p_metadata = jpeg_job_data->metadata; 2425 } 2426 2427 jpg_job.encode_job.hal_version = CAM_HAL_V1; 2428 m_parent->mExifParams.sensor_params.sens_type = m_parent->getSensorType(); 2429 jpg_job.encode_job.cam_exif_params = m_parent->mExifParams; 2430 jpg_job.encode_job.cam_exif_params.debug_params = 2431 (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t)); 2432 if (!jpg_job.encode_job.cam_exif_params.debug_params) { 2433 LOGE("Out of Memory. Allocation failed for 3A debug exif params"); 2434 return NO_MEMORY; 2435 } 2436 2437 jpg_job.encode_job.mobicat_mask = m_parent->mParameters.getMobicatMask(); 2438 2439 2440 if (NULL != jpg_job.encode_job.p_metadata && (jpg_job.encode_job.mobicat_mask > 0)) { 2441 2442 if (m_parent->mExifParams.debug_params) { 2443 memcpy(jpg_job.encode_job.cam_exif_params.debug_params, 2444 m_parent->mExifParams.debug_params, (sizeof(mm_jpeg_debug_exif_params_t))); 2445 2446 /* Save a copy of mobicat params */ 2447 jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid = 2448 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid; 2449 2450 if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) { 2451 jpg_job.encode_job.p_metadata->mobicat_aec_params = 2452 jpg_job.encode_job.cam_exif_params.cam_3a_params; 2453 } 2454 2455 /* Save a copy of 3A debug params */ 2456 jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid = 2457 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid; 2458 jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid = 2459 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid; 2460 jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid = 2461 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid; 2462 jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid = 2463 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid; 2464 jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid = 2465 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid; 2466 jpg_job.encode_job.p_metadata->is_statsdebug_bestats_params_valid = 2467 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid; 2468 jpg_job.encode_job.p_metadata->is_statsdebug_bhist_params_valid = 2469 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid; 2470 jpg_job.encode_job.p_metadata->is_statsdebug_3a_tuning_params_valid = 2471 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid; 2472 2473 if (jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid) { 2474 jpg_job.encode_job.p_metadata->statsdebug_ae_data = 2475 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params; 2476 } 2477 if (jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid) { 2478 jpg_job.encode_job.p_metadata->statsdebug_awb_data = 2479 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params; 2480 } 2481 if (jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid) { 2482 jpg_job.encode_job.p_metadata->statsdebug_af_data = 2483 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params; 2484 } 2485 if (jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid) { 2486 jpg_job.encode_job.p_metadata->statsdebug_asd_data = 2487 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params; 2488 } 2489 if (jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid) { 2490 jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data = 2491 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params; 2492 } 2493 if (jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid) { 2494 jpg_job.encode_job.p_metadata->statsdebug_bestats_buffer_data = 2495 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params; 2496 } 2497 if (jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid) { 2498 jpg_job.encode_job.p_metadata->statsdebug_bhist_data = 2499 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params; 2500 } 2501 if (jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid) { 2502 jpg_job.encode_job.p_metadata->statsdebug_3a_tuning_data = 2503 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params; 2504 } 2505 } 2506 2507 } 2508 2509 /* Init the QTable */ 2510 for (int i = 0; i < QTABLE_MAX; i++) { 2511 jpg_job.encode_job.qtable_set[i] = 0; 2512 } 2513 2514 const cam_sync_related_sensors_event_info_t* related_cam_info = 2515 m_parent->getRelatedCamSyncInfo(); 2516 if (related_cam_info->sync_control == CAM_SYNC_RELATED_SENSORS_ON && 2517 m_parent->getMpoComposition()) { 2518 jpg_job.encode_job.multi_image_info.type = MM_JPEG_TYPE_MPO; 2519 if (related_cam_info->type == CAM_TYPE_MAIN ) { 2520 jpg_job.encode_job.multi_image_info.is_primary = TRUE; 2521 LOGD("Encoding MPO Primary JPEG"); 2522 } else { 2523 jpg_job.encode_job.multi_image_info.is_primary = FALSE; 2524 LOGD("Encoding MPO Aux JPEG"); 2525 } 2526 jpg_job.encode_job.multi_image_info.num_of_images = 2; 2527 } else { 2528 LOGD("Encoding Single JPEG"); 2529 jpg_job.encode_job.multi_image_info.type = MM_JPEG_TYPE_JPEG; 2530 jpg_job.encode_job.multi_image_info.is_primary = FALSE; 2531 jpg_job.encode_job.multi_image_info.num_of_images = 1; 2532 } 2533 2534 LOGI("[KPI Perf] : PROFILE_JPEG_JOB_START"); 2535 ret = mJpegHandle.start_job(&jpg_job, &jobId); 2536 if (jpg_job.encode_job.cam_exif_params.debug_params) { 2537 free(jpg_job.encode_job.cam_exif_params.debug_params); 2538 } 2539 if (ret == NO_ERROR) { 2540 // remember job info 2541 jpeg_job_data->jobId = jobId; 2542 } 2543 2544 return ret; 2545 } 2546 2547 /*=========================================================================== 2548 * FUNCTION : processRawImageImpl 2549 * 2550 * DESCRIPTION: function to send raw image to upper layer 2551 * 2552 * PARAMETERS : 2553 * @recvd_frame : frame to be encoded 2554 * 2555 * RETURN : int32_t type of status 2556 * NO_ERROR -- success 2557 * none-zero failure code 2558 *==========================================================================*/ 2559 int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_frame) 2560 { 2561 int32_t rc = NO_ERROR; 2562 2563 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id); 2564 QCameraStream *pStream = NULL; 2565 mm_camera_buf_def_t *frame = NULL; 2566 // check reprocess channel if not found 2567 if (pChannel == NULL) { 2568 for (int8_t i = 0; i < mPPChannelCount; i++) { 2569 if ((mPPChannels[i] != NULL) && 2570 (validate_handle(mPPChannels[i]->getMyHandle(), recvd_frame->ch_id))) { 2571 pChannel = mPPChannels[i]; 2572 break; 2573 } 2574 } 2575 } 2576 if (pChannel == NULL) { 2577 LOGE("No corresponding channel (ch_id = %d) exist, return here", 2578 recvd_frame->ch_id); 2579 return BAD_VALUE; 2580 } 2581 2582 // find snapshot frame 2583 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) { 2584 QCameraStream *pCurStream = 2585 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id); 2586 if (pCurStream != NULL) { 2587 if (pCurStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 2588 pCurStream->isTypeOf(CAM_STREAM_TYPE_RAW) || 2589 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 2590 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)) { 2591 pStream = pCurStream; 2592 frame = recvd_frame->bufs[i]; 2593 break; 2594 } 2595 } 2596 } 2597 2598 if ( NULL == frame ) { 2599 LOGE("No valid raw buffer"); 2600 return BAD_VALUE; 2601 } 2602 2603 QCameraMemory *rawMemObj = (QCameraMemory *)frame->mem_info; 2604 bool zslChannelUsed = m_parent->isZSLMode() && 2605 ( pChannel != mPPChannels[0] ); 2606 camera_memory_t *raw_mem = NULL; 2607 2608 if (rawMemObj != NULL) { 2609 if (zslChannelUsed) { 2610 raw_mem = rawMemObj->getMemory(frame->buf_idx, false); 2611 } else { 2612 raw_mem = m_parent->mGetMemory(-1, 2613 frame->frame_len, 2614 1, 2615 m_parent->mCallbackCookie); 2616 if (NULL == raw_mem) { 2617 LOGE("Not enough memory for RAW cb "); 2618 return NO_MEMORY; 2619 } 2620 memcpy(raw_mem->data, frame->buffer, frame->frame_len); 2621 } 2622 } 2623 2624 if (NULL != rawMemObj && NULL != raw_mem) { 2625 // dump frame into file 2626 if (frame->stream_type == CAM_STREAM_TYPE_SNAPSHOT || 2627 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { 2628 // for YUV422 NV16 case 2629 m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_INPUT_JPEG); 2630 } else { 2631 //Received RAW snapshot taken notification 2632 m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_RAW); 2633 2634 if(true == m_parent->m_bIntRawEvtPending) { 2635 //Sending RAW snapshot taken notification to HAL 2636 memset(&m_dst_dim, 0, sizeof(m_dst_dim)); 2637 pStream->getFrameDimension(m_dst_dim); 2638 pthread_mutex_lock(&m_parent->m_int_lock); 2639 pthread_cond_signal(&m_parent->m_int_cond); 2640 pthread_mutex_unlock(&m_parent->m_int_lock); 2641 raw_mem->release(raw_mem); 2642 return rc; 2643 } 2644 } 2645 2646 // send data callback / notify for RAW_IMAGE 2647 if (NULL != m_parent->mDataCb && 2648 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) { 2649 qcamera_callback_argm_t cbArg; 2650 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 2651 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 2652 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE; 2653 cbArg.data = raw_mem; 2654 cbArg.index = 0; 2655 m_parent->m_cbNotifier.notifyCallback(cbArg); 2656 } 2657 if (NULL != m_parent->mNotifyCb && 2658 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) { 2659 qcamera_callback_argm_t cbArg; 2660 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 2661 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; 2662 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY; 2663 cbArg.ext1 = 0; 2664 cbArg.ext2 = 0; 2665 m_parent->m_cbNotifier.notifyCallback(cbArg); 2666 } 2667 2668 if ((m_parent->mDataCb != NULL) && 2669 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) > 0) { 2670 qcamera_release_data_t release_data; 2671 memset(&release_data, 0, sizeof(qcamera_release_data_t)); 2672 if ( zslChannelUsed ) { 2673 release_data.frame = recvd_frame; 2674 } else { 2675 release_data.data = raw_mem; 2676 } 2677 rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 2678 raw_mem, 2679 0, 2680 NULL, 2681 &release_data); 2682 } else { 2683 raw_mem->release(raw_mem); 2684 } 2685 } else { 2686 LOGE("Cannot get raw mem"); 2687 rc = UNKNOWN_ERROR; 2688 } 2689 2690 return rc; 2691 } 2692 2693 /*=========================================================================== 2694 * FUNCTION : dataSaveRoutine 2695 * 2696 * DESCRIPTION: data saving routine 2697 * 2698 * PARAMETERS : 2699 * @data : user data ptr (QCameraPostProcessor) 2700 * 2701 * RETURN : None 2702 *==========================================================================*/ 2703 void *QCameraPostProcessor::dataSaveRoutine(void *data) 2704 { 2705 int running = 1; 2706 int ret; 2707 uint8_t is_active = FALSE; 2708 QCameraPostProcessor *pme = (QCameraPostProcessor *)data; 2709 QCameraCmdThread *cmdThread = &pme->m_saveProcTh; 2710 cmdThread->setName("CAM_JpegSave"); 2711 char saveName[PROPERTY_VALUE_MAX]; 2712 2713 LOGH("E"); 2714 do { 2715 do { 2716 ret = cam_sem_wait(&cmdThread->cmd_sem); 2717 if (ret != 0 && errno != EINVAL) { 2718 LOGE("cam_sem_wait error (%s)", 2719 strerror(errno)); 2720 return NULL; 2721 } 2722 } while (ret != 0); 2723 2724 // we got notified about new cmd avail in cmd queue 2725 camera_cmd_type_t cmd = cmdThread->getCmd(); 2726 switch (cmd) { 2727 case CAMERA_CMD_TYPE_START_DATA_PROC: 2728 LOGH("start data proc"); 2729 is_active = TRUE; 2730 pme->m_inputSaveQ.init(); 2731 break; 2732 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 2733 { 2734 LOGH("stop data proc"); 2735 is_active = FALSE; 2736 2737 // flush input save Queue 2738 pme->m_inputSaveQ.flush(); 2739 2740 // signal cmd is completed 2741 cam_sem_post(&cmdThread->sync_sem); 2742 } 2743 break; 2744 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 2745 { 2746 LOGH("Do next job, active is %d", is_active); 2747 2748 qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) pme->m_inputSaveQ.dequeue(); 2749 if (job_data == NULL) { 2750 LOGE("Invalid jpeg event data"); 2751 continue; 2752 } 2753 //qcamera_jpeg_data_t *jpeg_job = 2754 // (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(false); 2755 //uint32_t frame_idx = jpeg_job->src_frame->bufs[0]->frame_idx; 2756 uint32_t frame_idx = 75; 2757 2758 pme->m_ongoingJpegQ.flushNodes(matchJobId, (void*)&job_data->jobId); 2759 2760 LOGH("[KPI Perf] : jpeg job %d", job_data->jobId); 2761 2762 if (is_active == TRUE) { 2763 memset(saveName, '\0', sizeof(saveName)); 2764 snprintf(saveName, 2765 sizeof(saveName), 2766 QCameraPostProcessor::STORE_LOCATION, 2767 pme->mSaveFrmCnt); 2768 2769 int file_fd = open(saveName, O_RDWR | O_CREAT, 0655); 2770 if (file_fd >= 0) { 2771 ssize_t written_len = write(file_fd, job_data->out_data.buf_vaddr, 2772 job_data->out_data.buf_filled_len); 2773 if ((ssize_t)job_data->out_data.buf_filled_len != written_len) { 2774 LOGE("Failed save complete data %d bytes " 2775 "written instead of %d bytes!", 2776 written_len, 2777 job_data->out_data.buf_filled_len); 2778 } else { 2779 LOGH("written number of bytes %d\n", 2780 written_len); 2781 } 2782 2783 close(file_fd); 2784 } else { 2785 LOGE("fail t open file for saving"); 2786 } 2787 pme->mSaveFrmCnt++; 2788 2789 camera_memory_t* jpeg_mem = pme->m_parent->mGetMemory(-1, 2790 strlen(saveName), 2791 1, 2792 pme->m_parent->mCallbackCookie); 2793 if (NULL == jpeg_mem) { 2794 ret = NO_MEMORY; 2795 LOGE("getMemory for jpeg, ret = NO_MEMORY"); 2796 goto end; 2797 } 2798 memcpy(jpeg_mem->data, saveName, strlen(saveName)); 2799 2800 LOGH("Calling upperlayer callback to store JPEG image"); 2801 qcamera_release_data_t release_data; 2802 memset(&release_data, 0, sizeof(qcamera_release_data_t)); 2803 release_data.data = jpeg_mem; 2804 release_data.unlinkFile = true; 2805 LOGI("[KPI Perf]: PROFILE_JPEG_CB "); 2806 ret = pme->sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 2807 jpeg_mem, 2808 0, 2809 NULL, 2810 &release_data, 2811 frame_idx); 2812 } 2813 2814 end: 2815 free(job_data); 2816 } 2817 break; 2818 case CAMERA_CMD_TYPE_EXIT: 2819 LOGH("save thread exit"); 2820 running = 0; 2821 break; 2822 default: 2823 break; 2824 } 2825 } while (running); 2826 LOGH("X"); 2827 return NULL; 2828 } 2829 2830 /*=========================================================================== 2831 * FUNCTION : dataProcessRoutine 2832 * 2833 * DESCRIPTION: data process routine that handles input data either from input 2834 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do 2835 * reprocess. 2836 * 2837 * PARAMETERS : 2838 * @data : user data ptr (QCameraPostProcessor) 2839 * 2840 * RETURN : None 2841 *==========================================================================*/ 2842 void *QCameraPostProcessor::dataProcessRoutine(void *data) 2843 { 2844 int running = 1; 2845 int ret; 2846 uint8_t is_active = FALSE; 2847 QCameraPostProcessor *pme = (QCameraPostProcessor *)data; 2848 QCameraCmdThread *cmdThread = &pme->m_dataProcTh; 2849 cmdThread->setName("CAM_DataProc"); 2850 2851 LOGH("E"); 2852 do { 2853 do { 2854 ret = cam_sem_wait(&cmdThread->cmd_sem); 2855 if (ret != 0 && errno != EINVAL) { 2856 LOGE("cam_sem_wait error (%s)", 2857 strerror(errno)); 2858 return NULL; 2859 } 2860 } while (ret != 0); 2861 2862 // we got notified about new cmd avail in cmd queue 2863 camera_cmd_type_t cmd = cmdThread->getCmd(); 2864 switch (cmd) { 2865 case CAMERA_CMD_TYPE_START_DATA_PROC: 2866 LOGH("start data proc"); 2867 is_active = TRUE; 2868 2869 pme->m_ongoingPPQ.init(); 2870 pme->m_inputJpegQ.init(); 2871 pme->m_inputPPQ.init(); 2872 pme->m_inputRawQ.init(); 2873 2874 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, 2875 FALSE, 2876 FALSE); 2877 2878 // signal cmd is completed 2879 cam_sem_post(&cmdThread->sync_sem); 2880 2881 break; 2882 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 2883 { 2884 LOGH("stop data proc"); 2885 is_active = FALSE; 2886 2887 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, 2888 TRUE, 2889 TRUE); 2890 // cancel all ongoing jpeg jobs 2891 qcamera_jpeg_data_t *jpeg_job = 2892 (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 2893 while (jpeg_job != NULL) { 2894 pme->mJpegHandle.abort_job(jpeg_job->jobId); 2895 2896 pme->releaseJpegJobData(jpeg_job); 2897 free(jpeg_job); 2898 2899 jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 2900 } 2901 2902 // destroy jpeg encoding session 2903 if ( 0 < pme->mJpegSessionId ) { 2904 pme->mJpegHandle.destroy_session(pme->mJpegSessionId); 2905 pme->mJpegSessionId = 0; 2906 } 2907 2908 // free jpeg out buf and exif obj 2909 FREE_JPEG_OUTPUT_BUFFER(pme->m_pJpegOutputMem, 2910 pme->m_JpegOutputMemCount); 2911 2912 if (pme->m_pJpegExifObj != NULL) { 2913 delete pme->m_pJpegExifObj; 2914 pme->m_pJpegExifObj = NULL; 2915 } 2916 2917 // flush ongoing postproc Queue 2918 pme->m_ongoingPPQ.flush(); 2919 2920 // flush input jpeg Queue 2921 pme->m_inputJpegQ.flush(); 2922 2923 // flush input Postproc Queue 2924 pme->m_inputPPQ.flush(); 2925 2926 // flush input raw Queue 2927 pme->m_inputRawQ.flush(); 2928 2929 // signal cmd is completed 2930 cam_sem_post(&cmdThread->sync_sem); 2931 2932 pme->mNewJpegSessionNeeded = true; 2933 } 2934 break; 2935 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 2936 { 2937 LOGH("Do next job, active is %d", is_active); 2938 if (is_active == TRUE) { 2939 qcamera_jpeg_data_t *jpeg_job = 2940 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 2941 2942 if (NULL != jpeg_job) { 2943 // To avoid any race conditions, 2944 // sync any stream specific parameters here. 2945 if (pme->m_parent->mParameters.isAdvCamFeaturesEnabled()) { 2946 // Sync stream params, only if advanced features configured 2947 // Reduces the latency for normal snapshot. 2948 pme->syncStreamParams(jpeg_job->src_frame, NULL); 2949 } 2950 2951 // add into ongoing jpeg job Q 2952 if (pme->m_ongoingJpegQ.enqueue((void *)jpeg_job)) { 2953 ret = pme->encodeData(jpeg_job, 2954 pme->mNewJpegSessionNeeded); 2955 if (NO_ERROR != ret) { 2956 // dequeue the last one 2957 pme->m_ongoingJpegQ.dequeue(false); 2958 pme->releaseJpegJobData(jpeg_job); 2959 free(jpeg_job); 2960 jpeg_job = NULL; 2961 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 2962 } 2963 } else { 2964 LOGW("m_ongoingJpegQ is not active!!!"); 2965 pme->releaseJpegJobData(jpeg_job); 2966 free(jpeg_job); 2967 jpeg_job = NULL; 2968 } 2969 } 2970 2971 2972 // process raw data if any 2973 mm_camera_super_buf_t *super_buf = 2974 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 2975 2976 if (NULL != super_buf) { 2977 //play shutter sound 2978 pme->m_parent->playShutter(); 2979 ret = pme->processRawImageImpl(super_buf); 2980 if (NO_ERROR != ret) { 2981 pme->releaseSuperBuf(super_buf); 2982 free(super_buf); 2983 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 2984 } 2985 } 2986 2987 ret = pme->doReprocess(); 2988 if (NO_ERROR != ret) { 2989 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 2990 } else { 2991 ret = pme->stopCapture(); 2992 } 2993 2994 } else { 2995 // not active, simply return buf and do no op 2996 qcamera_jpeg_data_t *jpeg_data = 2997 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 2998 if (NULL != jpeg_data) { 2999 pme->releaseJpegJobData(jpeg_data); 3000 free(jpeg_data); 3001 } 3002 mm_camera_super_buf_t *super_buf = 3003 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 3004 if (NULL != super_buf) { 3005 pme->releaseSuperBuf(super_buf); 3006 free(super_buf); 3007 } 3008 3009 // flush input Postproc Queue 3010 pme->m_inputPPQ.flush(); 3011 } 3012 } 3013 break; 3014 case CAMERA_CMD_TYPE_EXIT: 3015 running = 0; 3016 break; 3017 default: 3018 break; 3019 } 3020 } while (running); 3021 LOGH("X"); 3022 return NULL; 3023 } 3024 3025 /*=========================================================================== 3026 * FUNCTION : doReprocess 3027 * 3028 * DESCRIPTION: Trigger channel reprocessing 3029 * 3030 * PARAMETERS :None 3031 * 3032 * RETURN : int32_t type of status 3033 * NO_ERROR -- success 3034 * none-zero failure code 3035 *==========================================================================*/ 3036 int32_t QCameraPostProcessor::doReprocess() 3037 { 3038 int32_t ret = NO_ERROR; 3039 QCameraChannel *m_pSrcChannel = NULL; 3040 QCameraStream *pMetaStream = NULL; 3041 uint8_t meta_buf_index = 0; 3042 mm_camera_buf_def_t *meta_buf = NULL; 3043 mm_camera_super_buf_t *ppInputFrame = NULL; 3044 3045 qcamera_pp_data_t *ppreq_job = (qcamera_pp_data_t *)m_inputPPQ.peek(); 3046 if ((ppreq_job == NULL) || (ppreq_job->src_frame == NULL)) { 3047 return ret; 3048 } 3049 3050 if (!validatePostProcess(ppreq_job->src_frame)) { 3051 return ret; 3052 } 3053 3054 ppreq_job = (qcamera_pp_data_t *)m_inputPPQ.dequeue(); 3055 if (ppreq_job == NULL || ppreq_job->src_frame == NULL || 3056 ppreq_job->src_reproc_frame == NULL) { 3057 return ret; 3058 } 3059 3060 mm_camera_super_buf_t *src_frame = ppreq_job->src_frame; 3061 mm_camera_super_buf_t *src_reproc_frame = ppreq_job->src_reproc_frame; 3062 int8_t mCurReprocCount = ppreq_job->reprocCount; 3063 int8_t mCurChannelIdx = ppreq_job->ppChannelIndex; 3064 3065 LOGD("frame = %p src_frame = %p mCurReprocCount = %d mCurChannelIdx = %d", 3066 src_frame,src_reproc_frame,mCurReprocCount, mCurChannelIdx); 3067 3068 if ((m_parent->mParameters.getManualCaptureMode() >= 3069 CAM_MANUAL_CAPTURE_TYPE_3) && (mCurChannelIdx == 0)) { 3070 ppInputFrame = src_reproc_frame; 3071 } else { 3072 ppInputFrame = src_frame; 3073 } 3074 3075 if (mPPChannelCount >= CAM_PP_CHANNEL_MAX) { 3076 LOGE("invalid channel count"); 3077 return UNKNOWN_ERROR; 3078 } 3079 3080 // find meta data stream and index of meta data frame in the superbuf 3081 for (int8_t j = 0; j < mPPChannelCount; j++) { 3082 /*First search in src buffer for any offline metadata */ 3083 for (uint32_t i = 0; i < src_frame->num_bufs; i++) { 3084 QCameraStream *pStream = mPPChannels[j]->getStreamByHandle( 3085 src_frame->bufs[i]->stream_id); 3086 if (pStream != NULL && pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)) { 3087 meta_buf_index = (uint8_t) src_frame->bufs[i]->buf_idx; 3088 pMetaStream = pStream; 3089 meta_buf = src_frame->bufs[i]; 3090 break; 3091 } 3092 } 3093 3094 if ((pMetaStream != NULL) && (meta_buf != NULL)) { 3095 LOGD("Found Offline stream metadata = %d", 3096 (int)meta_buf_index); 3097 break; 3098 } 3099 } 3100 3101 if ((pMetaStream == NULL) && (meta_buf == NULL)) { 3102 for (int8_t j = 0; j < mPPChannelCount; j++) { 3103 m_pSrcChannel = mPPChannels[j]->getSrcChannel(); 3104 if (m_pSrcChannel == NULL) 3105 continue; 3106 for (uint32_t i = 0; i < src_reproc_frame->num_bufs; i++) { 3107 QCameraStream *pStream = 3108 m_pSrcChannel->getStreamByHandle( 3109 src_reproc_frame->bufs[i]->stream_id); 3110 if (pStream != NULL && pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) { 3111 meta_buf_index = (uint8_t) src_reproc_frame->bufs[i]->buf_idx; 3112 pMetaStream = pStream; 3113 meta_buf = src_reproc_frame->bufs[i]; 3114 break; 3115 } 3116 } 3117 if ((pMetaStream != NULL) && (meta_buf != NULL)) { 3118 LOGD("Found Meta data info for reprocessing index = %d", 3119 (int)meta_buf_index); 3120 break; 3121 } 3122 } 3123 } 3124 3125 if (m_parent->mParameters.isAdvCamFeaturesEnabled()) { 3126 // No need to sync stream params, if none of the advanced features configured 3127 // Reduces the latency for normal snapshot. 3128 syncStreamParams(src_frame, src_reproc_frame); 3129 } 3130 3131 if (mPPChannels[mCurChannelIdx] != NULL) { 3132 // add into ongoing PP job Q 3133 ppreq_job->reprocCount = (int8_t) (mCurReprocCount + 1); 3134 3135 if ((m_parent->needOfflineReprocessing()) || (ppreq_job->offline_buffer)) { 3136 m_bufCountPPQ++; 3137 if (m_ongoingPPQ.enqueue((void *)ppreq_job)) { 3138 pthread_mutex_lock(&m_reprocess_lock); 3139 ret = mPPChannels[mCurChannelIdx]->doReprocessOffline(ppInputFrame, 3140 meta_buf, m_parent->mParameters); 3141 if (ret != NO_ERROR) { 3142 pthread_mutex_unlock(&m_reprocess_lock); 3143 goto end; 3144 } 3145 3146 if ((ppreq_job->offline_buffer) && 3147 (ppreq_job->offline_reproc_buf)) { 3148 mPPChannels[mCurChannelIdx]->doReprocessOffline( 3149 ppreq_job->offline_reproc_buf, meta_buf); 3150 } 3151 pthread_mutex_unlock(&m_reprocess_lock); 3152 } else { 3153 LOGW("m_ongoingPPQ is not active!!!"); 3154 ret = UNKNOWN_ERROR; 3155 goto end; 3156 } 3157 } else { 3158 m_bufCountPPQ++; 3159 if (!m_ongoingPPQ.enqueue((void *)ppreq_job)) { 3160 LOGW("m_ongoingJpegQ is not active!!!"); 3161 ret = UNKNOWN_ERROR; 3162 goto end; 3163 } 3164 3165 int32_t numRequiredPPQBufsForSingleOutput = (int32_t) 3166 m_parent->mParameters.getNumberInBufsForSingleShot(); 3167 3168 if (m_bufCountPPQ % numRequiredPPQBufsForSingleOutput == 0) { 3169 int32_t extra_pp_job_count = 3170 m_parent->mParameters.getNumberOutBufsForSingleShot() - 3171 m_parent->mParameters.getNumberInBufsForSingleShot(); 3172 3173 for (int32_t i = 0; i < extra_pp_job_count; i++) { 3174 qcamera_pp_data_t *extra_pp_job = 3175 (qcamera_pp_data_t *)calloc(1, sizeof(qcamera_pp_data_t)); 3176 if (!extra_pp_job) { 3177 LOGE("no mem for qcamera_pp_data_t"); 3178 ret = NO_MEMORY; 3179 break; 3180 } 3181 extra_pp_job->reprocCount = ppreq_job->reprocCount; 3182 if (!m_ongoingPPQ.enqueue((void *)extra_pp_job)) { 3183 LOGW("m_ongoingJpegQ is not active!!!"); 3184 releaseOngoingPPData(extra_pp_job, this); 3185 free(extra_pp_job); 3186 extra_pp_job = NULL; 3187 goto end; 3188 } 3189 } 3190 } 3191 3192 ret = mPPChannels[mCurChannelIdx]->doReprocess(ppInputFrame, 3193 m_parent->mParameters, pMetaStream, meta_buf_index); 3194 } 3195 } else { 3196 LOGE("Reprocess channel is NULL"); 3197 ret = UNKNOWN_ERROR; 3198 } 3199 3200 end: 3201 if (ret != NO_ERROR) { 3202 releaseOngoingPPData(ppreq_job, this); 3203 if (ppreq_job != NULL) { 3204 free(ppreq_job); 3205 ppreq_job = NULL; 3206 } 3207 } 3208 return ret; 3209 } 3210 3211 /*=========================================================================== 3212 * FUNCTION : getReprocChannel 3213 * 3214 * DESCRIPTION: Returns reprocessing channel handle 3215 * 3216 * PARAMETERS : index for reprocessing array 3217 * 3218 * RETURN : QCameraReprocessChannel * type of pointer 3219 NULL if no reprocessing channel 3220 *==========================================================================*/ 3221 QCameraReprocessChannel * QCameraPostProcessor::getReprocChannel(uint8_t index) 3222 { 3223 if (index >= mPPChannelCount) { 3224 LOGE("Invalid index value"); 3225 return NULL; 3226 } 3227 return mPPChannels[index]; 3228 } 3229 3230 /*=========================================================================== 3231 * FUNCTION : stopCapture 3232 * 3233 * DESCRIPTION: Trigger image capture stop 3234 * 3235 * PARAMETERS : 3236 * None 3237 * 3238 * RETURN : int32_t type of status 3239 * NO_ERROR -- success 3240 * none-zero failure code 3241 *==========================================================================*/ 3242 int32_t QCameraPostProcessor::stopCapture() 3243 { 3244 int rc = NO_ERROR; 3245 3246 if (m_parent->isRegularCapture()) { 3247 rc = m_parent->processAPI( 3248 QCAMERA_SM_EVT_STOP_CAPTURE_CHANNEL, 3249 NULL); 3250 } 3251 return rc; 3252 } 3253 3254 /*=========================================================================== 3255 * FUNCTION : getJpegPaddingReq 3256 * 3257 * DESCRIPTION: function to add an entry to exif data 3258 * 3259 * PARAMETERS : 3260 * @padding_info : jpeg specific padding requirement 3261 * 3262 * RETURN : int32_t type of status 3263 * NO_ERROR -- success 3264 * none-zero failure code 3265 *==========================================================================*/ 3266 int32_t QCameraPostProcessor::getJpegPaddingReq(cam_padding_info_t &padding_info) 3267 { 3268 // TODO: hardcode for now, needs to query from mm-jpeg-interface 3269 padding_info.width_padding = CAM_PAD_NONE; 3270 padding_info.height_padding = CAM_PAD_TO_16; 3271 padding_info.plane_padding = CAM_PAD_TO_WORD; 3272 padding_info.offset_info.offset_x = 0; 3273 padding_info.offset_info.offset_y = 0; 3274 return NO_ERROR; 3275 } 3276 3277 /*=========================================================================== 3278 * FUNCTION : setYUVFrameInfo 3279 * 3280 * DESCRIPTION: set Raw YUV frame data info for up-layer 3281 * 3282 * PARAMETERS : 3283 * @frame : process frame received from mm-camera-interface 3284 * 3285 * RETURN : int32_t type of status 3286 * NO_ERROR -- success 3287 * none-zero failure code 3288 * 3289 * NOTE : currently we return frame len, y offset, cbcr offset and frame format 3290 *==========================================================================*/ 3291 int32_t QCameraPostProcessor::setYUVFrameInfo(mm_camera_super_buf_t *recvd_frame) 3292 { 3293 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id); 3294 // check reprocess channel if not found 3295 if (pChannel == NULL) { 3296 for (int8_t i = 0; i < mPPChannelCount; i++) { 3297 if ((mPPChannels[i] != NULL) && 3298 (validate_handle(mPPChannels[i]->getMyHandle(), recvd_frame->ch_id))) { 3299 pChannel = mPPChannels[i]; 3300 break; 3301 } 3302 } 3303 } 3304 3305 if (pChannel == NULL) { 3306 LOGE("No corresponding channel (ch_id = %d) exist, return here", 3307 recvd_frame->ch_id); 3308 return BAD_VALUE; 3309 } 3310 3311 // find snapshot frame 3312 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) { 3313 QCameraStream *pStream = 3314 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id); 3315 if (pStream != NULL) { 3316 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 3317 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { 3318 //get the main frame, use stream info 3319 cam_frame_len_offset_t frame_offset; 3320 cam_dimension_t frame_dim; 3321 cam_format_t frame_fmt; 3322 const char *fmt_string; 3323 pStream->getFrameDimension(frame_dim); 3324 pStream->getFrameOffset(frame_offset); 3325 pStream->getFormat(frame_fmt); 3326 fmt_string = m_parent->mParameters.getFrameFmtString(frame_fmt); 3327 3328 int cbcr_offset = (int32_t)frame_offset.mp[0].len - 3329 frame_dim.width * frame_dim.height; 3330 3331 LOGH("frame width=%d, height=%d, yoff=%d, cbcroff=%d, fmt_string=%s", 3332 frame_dim.width, frame_dim.height, frame_offset.mp[0].offset, cbcr_offset, fmt_string); 3333 return NO_ERROR; 3334 } 3335 } 3336 } 3337 3338 return BAD_VALUE; 3339 } 3340 3341 bool QCameraPostProcessor::matchJobId(void *data, void *, void *match_data) 3342 { 3343 qcamera_jpeg_data_t * job = (qcamera_jpeg_data_t *) data; 3344 uint32_t job_id = *((uint32_t *) match_data); 3345 return job->jobId == job_id; 3346 } 3347 3348 /*=========================================================================== 3349 * FUNCTION : getJpegMemory 3350 * 3351 * DESCRIPTION: buffer allocation function 3352 * to pass to jpeg interface 3353 * 3354 * PARAMETERS : 3355 * @out_buf : buffer descriptor struct 3356 * 3357 * RETURN : int32_t type of status 3358 * NO_ERROR -- success 3359 * none-zero failure code 3360 *==========================================================================*/ 3361 int QCameraPostProcessor::getJpegMemory(omx_jpeg_ouput_buf_t *out_buf) 3362 { 3363 LOGH("Allocating jpeg out buffer of size: %d", out_buf->size); 3364 QCameraPostProcessor *procInst = (QCameraPostProcessor *) out_buf->handle; 3365 camera_memory_t *cam_mem = procInst->m_parent->mGetMemory(out_buf->fd, out_buf->size, 1U, 3366 procInst->m_parent->mCallbackCookie); 3367 out_buf->mem_hdl = cam_mem; 3368 out_buf->vaddr = cam_mem->data; 3369 3370 return 0; 3371 } 3372 3373 /*=========================================================================== 3374 * FUNCTION : releaseJpegMemory 3375 * 3376 * DESCRIPTION: release jpeg memory function 3377 * to pass to jpeg interface, in case of abort 3378 * 3379 * PARAMETERS : 3380 * @out_buf : buffer descriptor struct 3381 * 3382 * RETURN : int32_t type of status 3383 * NO_ERROR -- success 3384 * none-zero failure code 3385 *==========================================================================*/ 3386 int QCameraPostProcessor::releaseJpegMemory(omx_jpeg_ouput_buf_t *out_buf) 3387 { 3388 if (out_buf && out_buf->mem_hdl) { 3389 LOGD("releasing jpeg out buffer of size: %d", out_buf->size); 3390 camera_memory_t *cam_mem = (camera_memory_t*)out_buf->mem_hdl; 3391 cam_mem->release(cam_mem); 3392 out_buf->mem_hdl = NULL; 3393 out_buf->vaddr = NULL; 3394 return NO_ERROR; 3395 } 3396 return -1; 3397 } 3398 3399 /*=========================================================================== 3400 * FUNCTION : QCameraExif 3401 * 3402 * DESCRIPTION: constructor of QCameraExif 3403 * 3404 * PARAMETERS : None 3405 * 3406 * RETURN : None 3407 *==========================================================================*/ 3408 QCameraExif::QCameraExif() 3409 : m_nNumEntries(0) 3410 { 3411 memset(m_Entries, 0, sizeof(m_Entries)); 3412 } 3413 3414 /*=========================================================================== 3415 * FUNCTION : ~QCameraExif 3416 * 3417 * DESCRIPTION: deconstructor of QCameraExif. Will release internal memory ptr. 3418 * 3419 * PARAMETERS : None 3420 * 3421 * RETURN : None 3422 *==========================================================================*/ 3423 QCameraExif::~QCameraExif() 3424 { 3425 for (uint32_t i = 0; i < m_nNumEntries; i++) { 3426 switch (m_Entries[i].tag_entry.type) { 3427 case EXIF_BYTE: 3428 { 3429 if (m_Entries[i].tag_entry.count > 1 && 3430 m_Entries[i].tag_entry.data._bytes != NULL) { 3431 free(m_Entries[i].tag_entry.data._bytes); 3432 m_Entries[i].tag_entry.data._bytes = NULL; 3433 } 3434 } 3435 break; 3436 case EXIF_ASCII: 3437 { 3438 if (m_Entries[i].tag_entry.data._ascii != NULL) { 3439 free(m_Entries[i].tag_entry.data._ascii); 3440 m_Entries[i].tag_entry.data._ascii = NULL; 3441 } 3442 } 3443 break; 3444 case EXIF_SHORT: 3445 { 3446 if (m_Entries[i].tag_entry.count > 1 && 3447 m_Entries[i].tag_entry.data._shorts != NULL) { 3448 free(m_Entries[i].tag_entry.data._shorts); 3449 m_Entries[i].tag_entry.data._shorts = NULL; 3450 } 3451 } 3452 break; 3453 case EXIF_LONG: 3454 { 3455 if (m_Entries[i].tag_entry.count > 1 && 3456 m_Entries[i].tag_entry.data._longs != NULL) { 3457 free(m_Entries[i].tag_entry.data._longs); 3458 m_Entries[i].tag_entry.data._longs = NULL; 3459 } 3460 } 3461 break; 3462 case EXIF_RATIONAL: 3463 { 3464 if (m_Entries[i].tag_entry.count > 1 && 3465 m_Entries[i].tag_entry.data._rats != NULL) { 3466 free(m_Entries[i].tag_entry.data._rats); 3467 m_Entries[i].tag_entry.data._rats = NULL; 3468 } 3469 } 3470 break; 3471 case EXIF_UNDEFINED: 3472 { 3473 if (m_Entries[i].tag_entry.data._undefined != NULL) { 3474 free(m_Entries[i].tag_entry.data._undefined); 3475 m_Entries[i].tag_entry.data._undefined = NULL; 3476 } 3477 } 3478 break; 3479 case EXIF_SLONG: 3480 { 3481 if (m_Entries[i].tag_entry.count > 1 && 3482 m_Entries[i].tag_entry.data._slongs != NULL) { 3483 free(m_Entries[i].tag_entry.data._slongs); 3484 m_Entries[i].tag_entry.data._slongs = NULL; 3485 } 3486 } 3487 break; 3488 case EXIF_SRATIONAL: 3489 { 3490 if (m_Entries[i].tag_entry.count > 1 && 3491 m_Entries[i].tag_entry.data._srats != NULL) { 3492 free(m_Entries[i].tag_entry.data._srats); 3493 m_Entries[i].tag_entry.data._srats = NULL; 3494 } 3495 } 3496 break; 3497 } 3498 } 3499 } 3500 3501 /*=========================================================================== 3502 * FUNCTION : addEntry 3503 * 3504 * DESCRIPTION: function to add an entry to exif data 3505 * 3506 * PARAMETERS : 3507 * @tagid : exif tag ID 3508 * @type : data type 3509 * @count : number of data in uint of its type 3510 * @data : input data ptr 3511 * 3512 * RETURN : int32_t type of status 3513 * NO_ERROR -- success 3514 * none-zero failure code 3515 *==========================================================================*/ 3516 int32_t QCameraExif::addEntry(exif_tag_id_t tagid, 3517 exif_tag_type_t type, 3518 uint32_t count, 3519 void *data) 3520 { 3521 int32_t rc = NO_ERROR; 3522 if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) { 3523 LOGE("Number of entries exceeded limit"); 3524 return NO_MEMORY; 3525 } 3526 3527 m_Entries[m_nNumEntries].tag_id = tagid; 3528 m_Entries[m_nNumEntries].tag_entry.type = type; 3529 m_Entries[m_nNumEntries].tag_entry.count = count; 3530 m_Entries[m_nNumEntries].tag_entry.copy = 1; 3531 switch (type) { 3532 case EXIF_BYTE: 3533 { 3534 if (count > 1) { 3535 uint8_t *values = (uint8_t *)malloc(count); 3536 if (values == NULL) { 3537 LOGE("No memory for byte array"); 3538 rc = NO_MEMORY; 3539 } else { 3540 memcpy(values, data, count); 3541 m_Entries[m_nNumEntries].tag_entry.data._bytes = values; 3542 } 3543 } else { 3544 m_Entries[m_nNumEntries].tag_entry.data._byte = *(uint8_t *)data; 3545 } 3546 } 3547 break; 3548 case EXIF_ASCII: 3549 { 3550 char *str = NULL; 3551 str = (char *)malloc(count + 1); 3552 if (str == NULL) { 3553 LOGE("No memory for ascii string"); 3554 rc = NO_MEMORY; 3555 } else { 3556 memset(str, 0, count + 1); 3557 memcpy(str, data, count); 3558 m_Entries[m_nNumEntries].tag_entry.data._ascii = str; 3559 } 3560 } 3561 break; 3562 case EXIF_SHORT: 3563 { 3564 uint16_t *exif_data = (uint16_t *)data; 3565 if (count > 1) { 3566 uint16_t *values = (uint16_t *)malloc(count * sizeof(uint16_t)); 3567 if (values == NULL) { 3568 LOGE("No memory for short array"); 3569 rc = NO_MEMORY; 3570 } else { 3571 memcpy(values, exif_data, count * sizeof(uint16_t)); 3572 m_Entries[m_nNumEntries].tag_entry.data._shorts = values; 3573 } 3574 } else { 3575 m_Entries[m_nNumEntries].tag_entry.data._short = *(uint16_t *)data; 3576 } 3577 } 3578 break; 3579 case EXIF_LONG: 3580 { 3581 uint32_t *exif_data = (uint32_t *)data; 3582 if (count > 1) { 3583 uint32_t *values = (uint32_t *)malloc(count * sizeof(uint32_t)); 3584 if (values == NULL) { 3585 LOGE("No memory for long array"); 3586 rc = NO_MEMORY; 3587 } else { 3588 memcpy(values, exif_data, count * sizeof(uint32_t)); 3589 m_Entries[m_nNumEntries].tag_entry.data._longs = values; 3590 } 3591 } else { 3592 m_Entries[m_nNumEntries].tag_entry.data._long = *(uint32_t *)data; 3593 } 3594 } 3595 break; 3596 case EXIF_RATIONAL: 3597 { 3598 rat_t *exif_data = (rat_t *)data; 3599 if (count > 1) { 3600 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t)); 3601 if (values == NULL) { 3602 LOGE("No memory for rational array"); 3603 rc = NO_MEMORY; 3604 } else { 3605 memcpy(values, exif_data, count * sizeof(rat_t)); 3606 m_Entries[m_nNumEntries].tag_entry.data._rats = values; 3607 } 3608 } else { 3609 m_Entries[m_nNumEntries].tag_entry.data._rat = *(rat_t *)data; 3610 } 3611 } 3612 break; 3613 case EXIF_UNDEFINED: 3614 { 3615 uint8_t *values = (uint8_t *)malloc(count); 3616 if (values == NULL) { 3617 LOGE("No memory for undefined array"); 3618 rc = NO_MEMORY; 3619 } else { 3620 memcpy(values, data, count); 3621 m_Entries[m_nNumEntries].tag_entry.data._undefined = values; 3622 } 3623 } 3624 break; 3625 case EXIF_SLONG: 3626 { 3627 uint32_t *exif_data = (uint32_t *)data; 3628 if (count > 1) { 3629 int32_t *values = (int32_t *)malloc(count * sizeof(int32_t)); 3630 if (values == NULL) { 3631 LOGE("No memory for signed long array"); 3632 rc = NO_MEMORY; 3633 } else { 3634 memcpy(values, exif_data, count * sizeof(int32_t)); 3635 m_Entries[m_nNumEntries].tag_entry.data._slongs = values; 3636 } 3637 } else { 3638 m_Entries[m_nNumEntries].tag_entry.data._slong = *(int32_t *)data; 3639 } 3640 } 3641 break; 3642 case EXIF_SRATIONAL: 3643 { 3644 srat_t *exif_data = (srat_t *)data; 3645 if (count > 1) { 3646 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t)); 3647 if (values == NULL) { 3648 LOGE("No memory for signed rational array"); 3649 rc = NO_MEMORY; 3650 } else { 3651 memcpy(values, exif_data, count * sizeof(srat_t)); 3652 m_Entries[m_nNumEntries].tag_entry.data._srats = values; 3653 } 3654 } else { 3655 m_Entries[m_nNumEntries].tag_entry.data._srat = *(srat_t *)data; 3656 } 3657 } 3658 break; 3659 } 3660 3661 // Increase number of entries 3662 m_nNumEntries++; 3663 return rc; 3664 } 3665 3666 }; // namespace qcamera 3667