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