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