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 m_parent->m_cbNotifier.notifyCallback(cbArg); 2157 } 2158 if (NULL != m_parent->mNotifyCb && 2159 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) { 2160 qcamera_callback_argm_t cbArg; 2161 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 2162 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; 2163 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY; 2164 cbArg.ext1 = 0; 2165 cbArg.ext2 = 0; 2166 m_parent->m_cbNotifier.notifyCallback(cbArg); 2167 } 2168 2169 if (mJpegClientHandle <= 0) { 2170 LOGE("Error: bug here, mJpegClientHandle is 0"); 2171 return UNKNOWN_ERROR; 2172 } 2173 2174 if (needNewSess) { 2175 // create jpeg encoding session 2176 mm_jpeg_encode_params_t encodeParam; 2177 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t)); 2178 ret = getJpegEncodingConfig(encodeParam, main_stream, thumb_stream); 2179 if (ret != NO_ERROR) { 2180 LOGE("error getting encoding config"); 2181 return ret; 2182 } 2183 LOGH("[KPI Perf] : call jpeg create_session"); 2184 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId); 2185 if (ret != NO_ERROR) { 2186 LOGE("error creating a new jpeg encoding session"); 2187 return ret; 2188 } 2189 needNewSess = FALSE; 2190 } 2191 // Fill in new job 2192 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t)); 2193 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE; 2194 jpg_job.encode_job.session_id = mJpegSessionId; 2195 jpg_job.encode_job.src_index = (int32_t)main_frame->buf_idx; 2196 jpg_job.encode_job.dst_index = 0; 2197 2198 if (mJpegMemOpt) { 2199 jpg_job.encode_job.dst_index = jpg_job.encode_job.src_index; 2200 } else if (mUseJpegBurst) { 2201 jpg_job.encode_job.dst_index = -1; 2202 } 2203 2204 // use src to reproc frame as work buffer; if src buf is not available 2205 // jpeg interface will allocate work buffer 2206 if (jpeg_job_data->src_reproc_frame != NULL) { 2207 int32_t ret = NO_ERROR; 2208 QCameraStream *main_stream = NULL; 2209 mm_camera_buf_def_t *main_frame = NULL; 2210 QCameraStream *thumb_stream = NULL; 2211 mm_camera_buf_def_t *thumb_frame = NULL; 2212 QCameraStream *reproc_stream = NULL; 2213 mm_camera_buf_def_t *workBuf = NULL; 2214 // Call queryStreams to fetch source of reproc frame 2215 ret = queryStreams(&main_stream, 2216 &thumb_stream, 2217 &reproc_stream, 2218 &main_frame, 2219 &thumb_frame, 2220 jpeg_job_data->src_reproc_frame, 2221 NULL); 2222 2223 if ((NO_ERROR == ret) && ((workBuf = main_frame) != NULL) 2224 && !m_parent->isLowPowerMode()) { 2225 camera_memory_t *camWorkMem = NULL; 2226 int workBufIndex = workBuf->buf_idx; 2227 QCameraMemory *workMem = (QCameraMemory *)workBuf->mem_info; 2228 if (workMem != NULL) { 2229 camWorkMem = workMem->getMemory(workBufIndex, false); 2230 } 2231 if (camWorkMem != NULL && workMem != NULL) { 2232 jpg_job.encode_job.work_buf.buf_size = camWorkMem->size; 2233 jpg_job.encode_job.work_buf.buf_vaddr = (uint8_t *)camWorkMem->data; 2234 jpg_job.encode_job.work_buf.fd = workMem->getFd(workBufIndex); 2235 workMem->invalidateCache(workBufIndex); 2236 } 2237 } 2238 } 2239 2240 cam_dimension_t src_dim; 2241 memset(&src_dim, 0, sizeof(cam_dimension_t)); 2242 main_stream->getFrameDimension(src_dim); 2243 2244 bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled(); 2245 bool img_feature_enabled = 2246 m_parent->mParameters.isUbiFocusEnabled() || 2247 m_parent->mParameters.isUbiRefocus() || 2248 m_parent->mParameters.isChromaFlashEnabled() || 2249 m_parent->mParameters.isOptiZoomEnabled() || 2250 m_parent->mParameters.isStillMoreEnabled(); 2251 2252 LOGH("Crop needed %d", img_feature_enabled); 2253 crop.left = 0; 2254 crop.top = 0; 2255 crop.height = src_dim.height; 2256 crop.width = src_dim.width; 2257 2258 param = main_stream->getOutputCrop(); 2259 for (int i = 0; i < param.outputCrop.num_of_streams; i++) { 2260 if (param.outputCrop.crop_info[i].stream_id 2261 == main_stream->getMyServerID()) { 2262 crop = param.outputCrop.crop_info[i].crop; 2263 main_stream->setCropInfo(crop); 2264 } 2265 } 2266 if (img_feature_enabled) { 2267 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 2268 2269 param = main_stream->getImgProp(); 2270 imgProp = param.imgProp; 2271 main_stream->setCropInfo(imgProp.crop); 2272 crop = imgProp.crop; 2273 thumb_stream = NULL; /* use thumbnail from main image */ 2274 2275 if ((reproc_stream != NULL) && (m_DataMem == NULL) && 2276 m_parent->mParameters.isUbiRefocus()) { 2277 2278 QCameraHeapMemory* miscBufHandler = reproc_stream->getMiscBuf(); 2279 cam_misc_buf_t* refocusResult = 2280 reinterpret_cast<cam_misc_buf_t *>(miscBufHandler->getPtr(0)); 2281 uint32_t resultSize = refocusResult->header_size + 2282 refocusResult->width * refocusResult->height; 2283 camera_memory_t *dataMem = m_parent->mGetMemory(-1, resultSize, 2284 1, m_parent->mCallbackCookie); 2285 2286 LOGH("Refocus result header %u dims %dx%d", 2287 resultSize, refocusResult->width, refocusResult->height); 2288 2289 if (dataMem && dataMem->data) { 2290 memcpy(dataMem->data, refocusResult->data, resultSize); 2291 //save mem pointer for depth map 2292 m_DataMem = dataMem; 2293 } 2294 } 2295 } else if ((reproc_stream != NULL) && (m_parent->mParameters.isTruePortraitEnabled())) { 2296 2297 QCameraHeapMemory* miscBufHandler = reproc_stream->getMiscBuf(); 2298 cam_misc_buf_t* tpResult = 2299 reinterpret_cast<cam_misc_buf_t *>(miscBufHandler->getPtr(0)); 2300 uint32_t tpMetaSize = tpResult->header_size + tpResult->width * tpResult->height; 2301 2302 LOGH("True portrait result header %d% dims dx%d", 2303 tpMetaSize, tpResult->width, tpResult->height); 2304 2305 CAM_DUMP_TO_FILE(QCAMERA_DUMP_FRM_LOCATION"tp", "bm", -1, "y", 2306 &tpResult->data, tpMetaSize); 2307 } 2308 2309 cam_dimension_t dst_dim; 2310 2311 if (hdr_output_crop && crop.height) { 2312 dst_dim.height = crop.height; 2313 } else { 2314 dst_dim.height = src_dim.height; 2315 } 2316 if (hdr_output_crop && crop.width) { 2317 dst_dim.width = crop.width; 2318 } else { 2319 dst_dim.width = src_dim.width; 2320 } 2321 2322 // main dim 2323 jpg_job.encode_job.main_dim.src_dim = src_dim; 2324 jpg_job.encode_job.main_dim.dst_dim = dst_dim; 2325 jpg_job.encode_job.main_dim.crop = crop; 2326 2327 // get 3a sw version info 2328 cam_q3a_version_t sw_version = 2329 m_parent->getCamHalCapabilities()->q3a_version; 2330 2331 // get exif data 2332 QCameraExif *pJpegExifObj = m_parent->getExifData(); 2333 jpeg_job_data->pJpegExifObj = pJpegExifObj; 2334 if (pJpegExifObj != NULL) { 2335 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries(); 2336 jpg_job.encode_job.exif_info.numOfEntries = 2337 pJpegExifObj->getNumOfEntries(); 2338 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] = 2339 sw_version.major_version; 2340 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] = 2341 sw_version.minor_version; 2342 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] = 2343 sw_version.patch_version; 2344 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] = 2345 sw_version.new_feature_des; 2346 } 2347 2348 // set rotation only when no online rotation or offline pp rotation is done before 2349 if (!m_parent->needRotationReprocess()) { 2350 jpg_job.encode_job.rotation = jpeg_rotation; 2351 } 2352 LOGH("jpeg rotation is set to %d", jpg_job.encode_job.rotation); 2353 2354 // thumbnail dim 2355 if (m_bThumbnailNeeded == TRUE) { 2356 m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim); 2357 2358 if (thumb_stream == NULL) { 2359 // need jpeg thumbnail, but no postview/preview stream exists 2360 // we use the main stream/frame to encode thumbnail 2361 thumb_stream = main_stream; 2362 thumb_frame = main_frame; 2363 } 2364 if (m_parent->needRotationReprocess() && 2365 ((90 == jpeg_rotation) || (270 == jpeg_rotation))) { 2366 // swap thumbnail dimensions 2367 cam_dimension_t tmp_dim = jpg_job.encode_job.thumb_dim.dst_dim; 2368 jpg_job.encode_job.thumb_dim.dst_dim.width = tmp_dim.height; 2369 jpg_job.encode_job.thumb_dim.dst_dim.height = tmp_dim.width; 2370 } 2371 2372 memset(&src_dim, 0, sizeof(cam_dimension_t)); 2373 thumb_stream->getFrameDimension(src_dim); 2374 jpg_job.encode_job.thumb_dim.src_dim = src_dim; 2375 2376 // crop is the same if frame is the same 2377 if (thumb_frame != main_frame) { 2378 crop.left = 0; 2379 crop.top = 0; 2380 crop.height = src_dim.height; 2381 crop.width = src_dim.width; 2382 2383 param = thumb_stream->getOutputCrop(); 2384 for (int i = 0; i < param.outputCrop.num_of_streams; i++) { 2385 if (param.outputCrop.crop_info[i].stream_id 2386 == thumb_stream->getMyServerID()) { 2387 crop = param.outputCrop.crop_info[i].crop; 2388 thumb_stream->setCropInfo(crop); 2389 } 2390 } 2391 } 2392 2393 2394 jpg_job.encode_job.thumb_dim.crop = crop; 2395 if (thumb_frame != NULL) { 2396 jpg_job.encode_job.thumb_index = thumb_frame->buf_idx; 2397 } 2398 LOGI("Thumbnail idx = %d src w/h (%dx%d), dst w/h (%dx%d)", 2399 jpg_job.encode_job.thumb_index, 2400 jpg_job.encode_job.thumb_dim.src_dim.width, 2401 jpg_job.encode_job.thumb_dim.src_dim.height, 2402 jpg_job.encode_job.thumb_dim.dst_dim.width, 2403 jpg_job.encode_job.thumb_dim.dst_dim.height); 2404 } 2405 2406 LOGI("Main image idx = %d src w/h (%dx%d), dst w/h (%dx%d)", 2407 jpg_job.encode_job.src_index, 2408 jpg_job.encode_job.main_dim.src_dim.width, 2409 jpg_job.encode_job.main_dim.src_dim.height, 2410 jpg_job.encode_job.main_dim.dst_dim.width, 2411 jpg_job.encode_job.main_dim.dst_dim.height); 2412 2413 if (thumb_frame != NULL) { 2414 // dump thumbnail frame if enabled 2415 m_parent->dumpFrameToFile(thumb_stream, thumb_frame, QCAMERA_DUMP_FRM_THUMBNAIL); 2416 } 2417 2418 if (jpeg_job_data->metadata != NULL) { 2419 // fill in meta data frame ptr 2420 jpg_job.encode_job.p_metadata = jpeg_job_data->metadata; 2421 } 2422 2423 jpg_job.encode_job.hal_version = CAM_HAL_V1; 2424 m_parent->mExifParams.sensor_params.sens_type = m_parent->getSensorType(); 2425 jpg_job.encode_job.cam_exif_params = m_parent->mExifParams; 2426 jpg_job.encode_job.cam_exif_params.debug_params = 2427 (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t)); 2428 if (!jpg_job.encode_job.cam_exif_params.debug_params) { 2429 LOGE("Out of Memory. Allocation failed for 3A debug exif params"); 2430 return NO_MEMORY; 2431 } 2432 2433 jpg_job.encode_job.mobicat_mask = m_parent->mParameters.getMobicatMask(); 2434 2435 2436 if (NULL != jpg_job.encode_job.p_metadata && (jpg_job.encode_job.mobicat_mask > 0)) { 2437 2438 if (m_parent->mExifParams.debug_params) { 2439 memcpy(jpg_job.encode_job.cam_exif_params.debug_params, 2440 m_parent->mExifParams.debug_params, (sizeof(mm_jpeg_debug_exif_params_t))); 2441 2442 /* Save a copy of mobicat params */ 2443 jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid = 2444 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid; 2445 2446 if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) { 2447 jpg_job.encode_job.p_metadata->mobicat_aec_params = 2448 jpg_job.encode_job.cam_exif_params.cam_3a_params; 2449 } 2450 2451 /* Save a copy of 3A debug params */ 2452 jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid = 2453 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid; 2454 jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid = 2455 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid; 2456 jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid = 2457 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid; 2458 jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid = 2459 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid; 2460 jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid = 2461 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid; 2462 jpg_job.encode_job.p_metadata->is_statsdebug_bestats_params_valid = 2463 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid; 2464 jpg_job.encode_job.p_metadata->is_statsdebug_bhist_params_valid = 2465 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid; 2466 jpg_job.encode_job.p_metadata->is_statsdebug_3a_tuning_params_valid = 2467 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid; 2468 2469 if (jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid) { 2470 jpg_job.encode_job.p_metadata->statsdebug_ae_data = 2471 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params; 2472 } 2473 if (jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid) { 2474 jpg_job.encode_job.p_metadata->statsdebug_awb_data = 2475 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params; 2476 } 2477 if (jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid) { 2478 jpg_job.encode_job.p_metadata->statsdebug_af_data = 2479 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params; 2480 } 2481 if (jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid) { 2482 jpg_job.encode_job.p_metadata->statsdebug_asd_data = 2483 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params; 2484 } 2485 if (jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid) { 2486 jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data = 2487 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params; 2488 } 2489 if (jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid) { 2490 jpg_job.encode_job.p_metadata->statsdebug_bestats_buffer_data = 2491 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params; 2492 } 2493 if (jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid) { 2494 jpg_job.encode_job.p_metadata->statsdebug_bhist_data = 2495 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params; 2496 } 2497 if (jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid) { 2498 jpg_job.encode_job.p_metadata->statsdebug_3a_tuning_data = 2499 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params; 2500 } 2501 } 2502 2503 } 2504 2505 /* Init the QTable */ 2506 for (int i = 0; i < QTABLE_MAX; i++) { 2507 jpg_job.encode_job.qtable_set[i] = 0; 2508 } 2509 2510 const cam_sync_related_sensors_event_info_t* related_cam_info = 2511 m_parent->getRelatedCamSyncInfo(); 2512 if (related_cam_info->sync_control == CAM_SYNC_RELATED_SENSORS_ON && 2513 m_parent->getMpoComposition()) { 2514 jpg_job.encode_job.multi_image_info.type = MM_JPEG_TYPE_MPO; 2515 if (related_cam_info->type == CAM_TYPE_MAIN ) { 2516 jpg_job.encode_job.multi_image_info.is_primary = TRUE; 2517 LOGD("Encoding MPO Primary JPEG"); 2518 } else { 2519 jpg_job.encode_job.multi_image_info.is_primary = FALSE; 2520 LOGD("Encoding MPO Aux JPEG"); 2521 } 2522 jpg_job.encode_job.multi_image_info.num_of_images = 2; 2523 } else { 2524 LOGD("Encoding Single JPEG"); 2525 jpg_job.encode_job.multi_image_info.type = MM_JPEG_TYPE_JPEG; 2526 jpg_job.encode_job.multi_image_info.is_primary = FALSE; 2527 jpg_job.encode_job.multi_image_info.num_of_images = 1; 2528 } 2529 2530 LOGI("[KPI Perf] : PROFILE_JPEG_JOB_START"); 2531 ret = mJpegHandle.start_job(&jpg_job, &jobId); 2532 if (jpg_job.encode_job.cam_exif_params.debug_params) { 2533 free(jpg_job.encode_job.cam_exif_params.debug_params); 2534 } 2535 if (ret == NO_ERROR) { 2536 // remember job info 2537 jpeg_job_data->jobId = jobId; 2538 } 2539 2540 return ret; 2541 } 2542 2543 /*=========================================================================== 2544 * FUNCTION : processRawImageImpl 2545 * 2546 * DESCRIPTION: function to send raw image to upper layer 2547 * 2548 * PARAMETERS : 2549 * @recvd_frame : frame to be encoded 2550 * 2551 * RETURN : int32_t type of status 2552 * NO_ERROR -- success 2553 * none-zero failure code 2554 *==========================================================================*/ 2555 int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_frame) 2556 { 2557 int32_t rc = NO_ERROR; 2558 2559 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id); 2560 QCameraStream *pStream = NULL; 2561 mm_camera_buf_def_t *frame = NULL; 2562 // check reprocess channel if not found 2563 if (pChannel == NULL) { 2564 for (int8_t i = 0; i < mPPChannelCount; i++) { 2565 if ((mPPChannels[i] != NULL) && 2566 (mPPChannels[i]->getMyHandle() == recvd_frame->ch_id)) { 2567 pChannel = mPPChannels[i]; 2568 break; 2569 } 2570 } 2571 } 2572 if (pChannel == NULL) { 2573 LOGE("No corresponding channel (ch_id = %d) exist, return here", 2574 recvd_frame->ch_id); 2575 return BAD_VALUE; 2576 } 2577 2578 // find snapshot frame 2579 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) { 2580 QCameraStream *pCurStream = 2581 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id); 2582 if (pCurStream != NULL) { 2583 if (pCurStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 2584 pCurStream->isTypeOf(CAM_STREAM_TYPE_RAW) || 2585 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 2586 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)) { 2587 pStream = pCurStream; 2588 frame = recvd_frame->bufs[i]; 2589 break; 2590 } 2591 } 2592 } 2593 2594 if ( NULL == frame ) { 2595 LOGE("No valid raw buffer"); 2596 return BAD_VALUE; 2597 } 2598 2599 QCameraMemory *rawMemObj = (QCameraMemory *)frame->mem_info; 2600 bool zslChannelUsed = m_parent->isZSLMode() && 2601 ( pChannel != mPPChannels[0] ); 2602 camera_memory_t *raw_mem = NULL; 2603 2604 if (rawMemObj != NULL) { 2605 if (zslChannelUsed) { 2606 raw_mem = rawMemObj->getMemory(frame->buf_idx, false); 2607 } else { 2608 raw_mem = m_parent->mGetMemory(-1, 2609 frame->frame_len, 2610 1, 2611 m_parent->mCallbackCookie); 2612 if (NULL == raw_mem) { 2613 LOGE("Not enough memory for RAW cb "); 2614 return NO_MEMORY; 2615 } 2616 memcpy(raw_mem->data, frame->buffer, frame->frame_len); 2617 } 2618 } 2619 2620 if (NULL != rawMemObj && NULL != raw_mem) { 2621 // dump frame into file 2622 if (frame->stream_type == CAM_STREAM_TYPE_SNAPSHOT || 2623 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { 2624 // for YUV422 NV16 case 2625 m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_SNAPSHOT); 2626 } else { 2627 //Received RAW snapshot taken notification 2628 m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_RAW); 2629 2630 if(true == m_parent->m_bIntRawEvtPending) { 2631 //Sending RAW snapshot taken notification to HAL 2632 memset(&m_dst_dim, 0, sizeof(m_dst_dim)); 2633 pStream->getFrameDimension(m_dst_dim); 2634 pthread_mutex_lock(&m_parent->m_int_lock); 2635 pthread_cond_signal(&m_parent->m_int_cond); 2636 pthread_mutex_unlock(&m_parent->m_int_lock); 2637 raw_mem->release(raw_mem); 2638 return rc; 2639 } 2640 } 2641 2642 // send data callback / notify for RAW_IMAGE 2643 if (NULL != m_parent->mDataCb && 2644 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) { 2645 qcamera_callback_argm_t cbArg; 2646 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 2647 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 2648 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE; 2649 cbArg.data = raw_mem; 2650 cbArg.index = 0; 2651 m_parent->m_cbNotifier.notifyCallback(cbArg); 2652 } 2653 if (NULL != m_parent->mNotifyCb && 2654 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) { 2655 qcamera_callback_argm_t cbArg; 2656 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 2657 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; 2658 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY; 2659 cbArg.ext1 = 0; 2660 cbArg.ext2 = 0; 2661 m_parent->m_cbNotifier.notifyCallback(cbArg); 2662 } 2663 2664 if ((m_parent->mDataCb != NULL) && 2665 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) > 0) { 2666 qcamera_release_data_t release_data; 2667 memset(&release_data, 0, sizeof(qcamera_release_data_t)); 2668 if ( zslChannelUsed ) { 2669 release_data.frame = recvd_frame; 2670 } else { 2671 release_data.data = raw_mem; 2672 } 2673 rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 2674 raw_mem, 2675 0, 2676 NULL, 2677 &release_data); 2678 } else { 2679 raw_mem->release(raw_mem); 2680 } 2681 } else { 2682 LOGE("Cannot get raw mem"); 2683 rc = UNKNOWN_ERROR; 2684 } 2685 2686 return rc; 2687 } 2688 2689 /*=========================================================================== 2690 * FUNCTION : dataSaveRoutine 2691 * 2692 * DESCRIPTION: data saving routine 2693 * 2694 * PARAMETERS : 2695 * @data : user data ptr (QCameraPostProcessor) 2696 * 2697 * RETURN : None 2698 *==========================================================================*/ 2699 void *QCameraPostProcessor::dataSaveRoutine(void *data) 2700 { 2701 int running = 1; 2702 int ret; 2703 uint8_t is_active = FALSE; 2704 QCameraPostProcessor *pme = (QCameraPostProcessor *)data; 2705 QCameraCmdThread *cmdThread = &pme->m_saveProcTh; 2706 cmdThread->setName("CAM_JpegSave"); 2707 char saveName[PROPERTY_VALUE_MAX]; 2708 2709 LOGH("E"); 2710 do { 2711 do { 2712 ret = cam_sem_wait(&cmdThread->cmd_sem); 2713 if (ret != 0 && errno != EINVAL) { 2714 LOGE("cam_sem_wait error (%s)", 2715 strerror(errno)); 2716 return NULL; 2717 } 2718 } while (ret != 0); 2719 2720 // we got notified about new cmd avail in cmd queue 2721 camera_cmd_type_t cmd = cmdThread->getCmd(); 2722 switch (cmd) { 2723 case CAMERA_CMD_TYPE_START_DATA_PROC: 2724 LOGH("start data proc"); 2725 is_active = TRUE; 2726 pme->m_inputSaveQ.init(); 2727 break; 2728 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 2729 { 2730 LOGH("stop data proc"); 2731 is_active = FALSE; 2732 2733 // flush input save Queue 2734 pme->m_inputSaveQ.flush(); 2735 2736 // signal cmd is completed 2737 cam_sem_post(&cmdThread->sync_sem); 2738 } 2739 break; 2740 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 2741 { 2742 LOGH("Do next job, active is %d", is_active); 2743 2744 qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) pme->m_inputSaveQ.dequeue(); 2745 if (job_data == NULL) { 2746 LOGE("Invalid jpeg event data"); 2747 continue; 2748 } 2749 //qcamera_jpeg_data_t *jpeg_job = 2750 // (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(false); 2751 //uint32_t frame_idx = jpeg_job->src_frame->bufs[0]->frame_idx; 2752 uint32_t frame_idx = 75; 2753 2754 pme->m_ongoingJpegQ.flushNodes(matchJobId, (void*)&job_data->jobId); 2755 2756 LOGH("[KPI Perf] : jpeg job %d", job_data->jobId); 2757 2758 if (is_active == TRUE) { 2759 memset(saveName, '\0', sizeof(saveName)); 2760 snprintf(saveName, 2761 sizeof(saveName), 2762 QCameraPostProcessor::STORE_LOCATION, 2763 pme->mSaveFrmCnt); 2764 2765 int file_fd = open(saveName, O_RDWR | O_CREAT, 0655); 2766 if (file_fd >= 0) { 2767 ssize_t written_len = write(file_fd, job_data->out_data.buf_vaddr, 2768 job_data->out_data.buf_filled_len); 2769 if ((ssize_t)job_data->out_data.buf_filled_len != written_len) { 2770 LOGE("Failed save complete data %d bytes " 2771 "written instead of %d bytes!", 2772 written_len, 2773 job_data->out_data.buf_filled_len); 2774 } else { 2775 LOGH("written number of bytes %d\n", 2776 written_len); 2777 } 2778 2779 close(file_fd); 2780 } else { 2781 LOGE("fail t open file for saving"); 2782 } 2783 pme->mSaveFrmCnt++; 2784 2785 camera_memory_t* jpeg_mem = pme->m_parent->mGetMemory(-1, 2786 strlen(saveName), 2787 1, 2788 pme->m_parent->mCallbackCookie); 2789 if (NULL == jpeg_mem) { 2790 ret = NO_MEMORY; 2791 LOGE("getMemory for jpeg, ret = NO_MEMORY"); 2792 goto end; 2793 } 2794 memcpy(jpeg_mem->data, saveName, strlen(saveName)); 2795 2796 LOGH("Calling upperlayer callback to store JPEG image"); 2797 qcamera_release_data_t release_data; 2798 memset(&release_data, 0, sizeof(qcamera_release_data_t)); 2799 release_data.data = jpeg_mem; 2800 release_data.unlinkFile = true; 2801 LOGI("[KPI Perf]: PROFILE_JPEG_CB "); 2802 ret = pme->sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 2803 jpeg_mem, 2804 0, 2805 NULL, 2806 &release_data, 2807 frame_idx); 2808 } 2809 2810 end: 2811 free(job_data); 2812 } 2813 break; 2814 case CAMERA_CMD_TYPE_EXIT: 2815 LOGH("save thread exit"); 2816 running = 0; 2817 break; 2818 default: 2819 break; 2820 } 2821 } while (running); 2822 LOGH("X"); 2823 return NULL; 2824 } 2825 2826 /*=========================================================================== 2827 * FUNCTION : dataProcessRoutine 2828 * 2829 * DESCRIPTION: data process routine that handles input data either from input 2830 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do 2831 * reprocess. 2832 * 2833 * PARAMETERS : 2834 * @data : user data ptr (QCameraPostProcessor) 2835 * 2836 * RETURN : None 2837 *==========================================================================*/ 2838 void *QCameraPostProcessor::dataProcessRoutine(void *data) 2839 { 2840 int running = 1; 2841 int ret; 2842 uint8_t is_active = FALSE; 2843 QCameraPostProcessor *pme = (QCameraPostProcessor *)data; 2844 QCameraCmdThread *cmdThread = &pme->m_dataProcTh; 2845 cmdThread->setName("CAM_DataProc"); 2846 2847 LOGH("E"); 2848 do { 2849 do { 2850 ret = cam_sem_wait(&cmdThread->cmd_sem); 2851 if (ret != 0 && errno != EINVAL) { 2852 LOGE("cam_sem_wait error (%s)", 2853 strerror(errno)); 2854 return NULL; 2855 } 2856 } while (ret != 0); 2857 2858 // we got notified about new cmd avail in cmd queue 2859 camera_cmd_type_t cmd = cmdThread->getCmd(); 2860 switch (cmd) { 2861 case CAMERA_CMD_TYPE_START_DATA_PROC: 2862 LOGH("start data proc"); 2863 is_active = TRUE; 2864 2865 pme->m_ongoingPPQ.init(); 2866 pme->m_inputJpegQ.init(); 2867 pme->m_inputPPQ.init(); 2868 pme->m_inputRawQ.init(); 2869 2870 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, 2871 FALSE, 2872 FALSE); 2873 2874 // signal cmd is completed 2875 cam_sem_post(&cmdThread->sync_sem); 2876 2877 break; 2878 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 2879 { 2880 LOGH("stop data proc"); 2881 is_active = FALSE; 2882 2883 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, 2884 TRUE, 2885 TRUE); 2886 // cancel all ongoing jpeg jobs 2887 qcamera_jpeg_data_t *jpeg_job = 2888 (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 2889 while (jpeg_job != NULL) { 2890 pme->mJpegHandle.abort_job(jpeg_job->jobId); 2891 2892 pme->releaseJpegJobData(jpeg_job); 2893 free(jpeg_job); 2894 2895 jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 2896 } 2897 2898 // destroy jpeg encoding session 2899 if ( 0 < pme->mJpegSessionId ) { 2900 pme->mJpegHandle.destroy_session(pme->mJpegSessionId); 2901 pme->mJpegSessionId = 0; 2902 } 2903 2904 // free jpeg out buf and exif obj 2905 FREE_JPEG_OUTPUT_BUFFER(pme->m_pJpegOutputMem, 2906 pme->m_JpegOutputMemCount); 2907 2908 if (pme->m_pJpegExifObj != NULL) { 2909 delete pme->m_pJpegExifObj; 2910 pme->m_pJpegExifObj = NULL; 2911 } 2912 2913 // flush ongoing postproc Queue 2914 pme->m_ongoingPPQ.flush(); 2915 2916 // flush input jpeg Queue 2917 pme->m_inputJpegQ.flush(); 2918 2919 // flush input Postproc Queue 2920 pme->m_inputPPQ.flush(); 2921 2922 // flush input raw Queue 2923 pme->m_inputRawQ.flush(); 2924 2925 // signal cmd is completed 2926 cam_sem_post(&cmdThread->sync_sem); 2927 2928 pme->mNewJpegSessionNeeded = true; 2929 } 2930 break; 2931 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 2932 { 2933 LOGH("Do next job, active is %d", is_active); 2934 if (is_active == TRUE) { 2935 qcamera_jpeg_data_t *jpeg_job = 2936 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 2937 2938 if (NULL != jpeg_job) { 2939 // To avoid any race conditions, 2940 // sync any stream specific parameters here. 2941 if (pme->m_parent->mParameters.isAdvCamFeaturesEnabled()) { 2942 // Sync stream params, only if advanced features configured 2943 // Reduces the latency for normal snapshot. 2944 pme->syncStreamParams(jpeg_job->src_frame, NULL); 2945 } 2946 2947 // add into ongoing jpeg job Q 2948 if (pme->m_ongoingJpegQ.enqueue((void *)jpeg_job)) { 2949 ret = pme->encodeData(jpeg_job, 2950 pme->mNewJpegSessionNeeded); 2951 if (NO_ERROR != ret) { 2952 // dequeue the last one 2953 pme->m_ongoingJpegQ.dequeue(false); 2954 pme->releaseJpegJobData(jpeg_job); 2955 free(jpeg_job); 2956 jpeg_job = NULL; 2957 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 2958 } 2959 } else { 2960 LOGW("m_ongoingJpegQ is not active!!!"); 2961 pme->releaseJpegJobData(jpeg_job); 2962 free(jpeg_job); 2963 jpeg_job = NULL; 2964 } 2965 } 2966 2967 2968 // process raw data if any 2969 mm_camera_super_buf_t *super_buf = 2970 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 2971 2972 if (NULL != super_buf) { 2973 //play shutter sound 2974 pme->m_parent->playShutter(); 2975 ret = pme->processRawImageImpl(super_buf); 2976 if (NO_ERROR != ret) { 2977 pme->releaseSuperBuf(super_buf); 2978 free(super_buf); 2979 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 2980 } 2981 } 2982 2983 ret = pme->doReprocess(); 2984 if (NO_ERROR != ret) { 2985 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 2986 } else { 2987 ret = pme->stopCapture(); 2988 } 2989 2990 } else { 2991 // not active, simply return buf and do no op 2992 qcamera_jpeg_data_t *jpeg_data = 2993 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 2994 if (NULL != jpeg_data) { 2995 pme->releaseJpegJobData(jpeg_data); 2996 free(jpeg_data); 2997 } 2998 mm_camera_super_buf_t *super_buf = 2999 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 3000 if (NULL != super_buf) { 3001 pme->releaseSuperBuf(super_buf); 3002 free(super_buf); 3003 } 3004 3005 // flush input Postproc Queue 3006 pme->m_inputPPQ.flush(); 3007 } 3008 } 3009 break; 3010 case CAMERA_CMD_TYPE_EXIT: 3011 running = 0; 3012 break; 3013 default: 3014 break; 3015 } 3016 } while (running); 3017 LOGH("X"); 3018 return NULL; 3019 } 3020 3021 /*=========================================================================== 3022 * FUNCTION : doReprocess 3023 * 3024 * DESCRIPTION: Trigger channel reprocessing 3025 * 3026 * PARAMETERS :None 3027 * 3028 * RETURN : int32_t type of status 3029 * NO_ERROR -- success 3030 * none-zero failure code 3031 *==========================================================================*/ 3032 int32_t QCameraPostProcessor::doReprocess() 3033 { 3034 int32_t ret = NO_ERROR; 3035 QCameraChannel *m_pSrcChannel = NULL; 3036 QCameraStream *pMetaStream = NULL; 3037 uint8_t meta_buf_index = 0; 3038 mm_camera_buf_def_t *meta_buf = NULL; 3039 mm_camera_super_buf_t *ppInputFrame = NULL; 3040 3041 qcamera_pp_data_t *ppreq_job = (qcamera_pp_data_t *)m_inputPPQ.peek(); 3042 if ((ppreq_job == NULL) || (ppreq_job->src_frame == NULL)) { 3043 return ret; 3044 } 3045 3046 if (!validatePostProcess(ppreq_job->src_frame)) { 3047 return ret; 3048 } 3049 3050 ppreq_job = (qcamera_pp_data_t *)m_inputPPQ.dequeue(); 3051 if (ppreq_job == NULL || ppreq_job->src_frame == NULL || 3052 ppreq_job->src_reproc_frame == NULL) { 3053 return ret; 3054 } 3055 3056 mm_camera_super_buf_t *src_frame = ppreq_job->src_frame; 3057 mm_camera_super_buf_t *src_reproc_frame = ppreq_job->src_reproc_frame; 3058 int8_t mCurReprocCount = ppreq_job->reprocCount; 3059 int8_t mCurChannelIdx = ppreq_job->ppChannelIndex; 3060 3061 LOGD("frame = %p src_frame = %p mCurReprocCount = %d mCurChannelIdx = %d", 3062 src_frame,src_reproc_frame,mCurReprocCount, mCurChannelIdx); 3063 3064 if ((m_parent->mParameters.getManualCaptureMode() >= 3065 CAM_MANUAL_CAPTURE_TYPE_3) && (mCurChannelIdx == 0)) { 3066 ppInputFrame = src_reproc_frame; 3067 } else { 3068 ppInputFrame = src_frame; 3069 } 3070 3071 if (mPPChannelCount >= CAM_PP_CHANNEL_MAX) { 3072 LOGE("invalid channel count"); 3073 return UNKNOWN_ERROR; 3074 } 3075 3076 // find meta data stream and index of meta data frame in the superbuf 3077 for (int8_t j = 0; j < mPPChannelCount; j++) { 3078 /*First search in src buffer for any offline metadata */ 3079 for (uint32_t i = 0; i < src_frame->num_bufs; i++) { 3080 QCameraStream *pStream = mPPChannels[j]->getStreamByHandle( 3081 src_frame->bufs[i]->stream_id); 3082 if (pStream != NULL && pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)) { 3083 meta_buf_index = (uint8_t) src_frame->bufs[i]->buf_idx; 3084 pMetaStream = pStream; 3085 meta_buf = src_frame->bufs[i]; 3086 break; 3087 } 3088 } 3089 3090 if ((pMetaStream != NULL) && (meta_buf != NULL)) { 3091 LOGD("Found Offline stream metadata = %d", 3092 (int)meta_buf_index); 3093 break; 3094 } 3095 } 3096 3097 if ((pMetaStream == NULL) && (meta_buf == NULL)) { 3098 for (int8_t j = 0; j < mPPChannelCount; j++) { 3099 m_pSrcChannel = mPPChannels[j]->getSrcChannel(); 3100 if (m_pSrcChannel == NULL) 3101 continue; 3102 for (uint32_t i = 0; i < src_reproc_frame->num_bufs; i++) { 3103 QCameraStream *pStream = 3104 m_pSrcChannel->getStreamByHandle( 3105 src_reproc_frame->bufs[i]->stream_id); 3106 if (pStream != NULL && pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) { 3107 meta_buf_index = (uint8_t) src_reproc_frame->bufs[i]->buf_idx; 3108 pMetaStream = pStream; 3109 meta_buf = src_reproc_frame->bufs[i]; 3110 break; 3111 } 3112 } 3113 if ((pMetaStream != NULL) && (meta_buf != NULL)) { 3114 LOGD("Found Meta data info for reprocessing index = %d", 3115 (int)meta_buf_index); 3116 break; 3117 } 3118 } 3119 } 3120 3121 if (m_parent->mParameters.isAdvCamFeaturesEnabled()) { 3122 // No need to sync stream params, if none of the advanced features configured 3123 // Reduces the latency for normal snapshot. 3124 syncStreamParams(src_frame, src_reproc_frame); 3125 } 3126 if (mPPChannels[mCurChannelIdx] != NULL) { 3127 // add into ongoing PP job Q 3128 ppreq_job->reprocCount = (int8_t) (mCurReprocCount + 1); 3129 3130 if ((m_parent->isRegularCapture()) || (ppreq_job->offline_buffer)) { 3131 m_bufCountPPQ++; 3132 if (m_ongoingPPQ.enqueue((void *)ppreq_job)) { 3133 pthread_mutex_lock(&m_reprocess_lock); 3134 ret = mPPChannels[mCurChannelIdx]->doReprocessOffline(ppInputFrame, 3135 meta_buf, m_parent->mParameters); 3136 if (ret != NO_ERROR) { 3137 pthread_mutex_unlock(&m_reprocess_lock); 3138 goto end; 3139 } 3140 3141 if ((ppreq_job->offline_buffer) && 3142 (ppreq_job->offline_reproc_buf)) { 3143 mPPChannels[mCurChannelIdx]->doReprocessOffline( 3144 ppreq_job->offline_reproc_buf, meta_buf); 3145 } 3146 pthread_mutex_unlock(&m_reprocess_lock); 3147 } else { 3148 LOGW("m_ongoingPPQ is not active!!!"); 3149 ret = UNKNOWN_ERROR; 3150 goto end; 3151 } 3152 } else { 3153 m_bufCountPPQ++; 3154 if (!m_ongoingPPQ.enqueue((void *)ppreq_job)) { 3155 LOGW("m_ongoingJpegQ is not active!!!"); 3156 ret = UNKNOWN_ERROR; 3157 goto end; 3158 } 3159 3160 int32_t numRequiredPPQBufsForSingleOutput = (int32_t) 3161 m_parent->mParameters.getNumberInBufsForSingleShot(); 3162 3163 if (m_bufCountPPQ % numRequiredPPQBufsForSingleOutput == 0) { 3164 int32_t extra_pp_job_count = 3165 m_parent->mParameters.getNumberOutBufsForSingleShot() - 3166 m_parent->mParameters.getNumberInBufsForSingleShot(); 3167 3168 for (int32_t i = 0; i < extra_pp_job_count; i++) { 3169 qcamera_pp_data_t *extra_pp_job = 3170 (qcamera_pp_data_t *)calloc(1, sizeof(qcamera_pp_data_t)); 3171 if (!extra_pp_job) { 3172 LOGE("no mem for qcamera_pp_data_t"); 3173 ret = NO_MEMORY; 3174 break; 3175 } 3176 extra_pp_job->reprocCount = ppreq_job->reprocCount; 3177 if (!m_ongoingPPQ.enqueue((void *)extra_pp_job)) { 3178 LOGW("m_ongoingJpegQ is not active!!!"); 3179 releaseOngoingPPData(extra_pp_job, this); 3180 free(extra_pp_job); 3181 extra_pp_job = NULL; 3182 goto end; 3183 } 3184 } 3185 } 3186 3187 ret = mPPChannels[mCurChannelIdx]->doReprocess(ppInputFrame, 3188 m_parent->mParameters, pMetaStream, meta_buf_index); 3189 } 3190 } else { 3191 LOGE("Reprocess channel is NULL"); 3192 ret = UNKNOWN_ERROR; 3193 } 3194 3195 end: 3196 if (ret != NO_ERROR) { 3197 releaseOngoingPPData(ppreq_job, this); 3198 if (ppreq_job != NULL) { 3199 free(ppreq_job); 3200 ppreq_job = NULL; 3201 } 3202 } 3203 return ret; 3204 } 3205 3206 /*=========================================================================== 3207 * FUNCTION : getReprocChannel 3208 * 3209 * DESCRIPTION: Returns reprocessing channel handle 3210 * 3211 * PARAMETERS : index for reprocessing array 3212 * 3213 * RETURN : QCameraReprocessChannel * type of pointer 3214 NULL if no reprocessing channel 3215 *==========================================================================*/ 3216 QCameraReprocessChannel * QCameraPostProcessor::getReprocChannel(uint8_t index) 3217 { 3218 if (index >= mPPChannelCount) { 3219 LOGE("Invalid index value"); 3220 return NULL; 3221 } 3222 return mPPChannels[index]; 3223 } 3224 3225 /*=========================================================================== 3226 * FUNCTION : stopCapture 3227 * 3228 * DESCRIPTION: Trigger image capture stop 3229 * 3230 * PARAMETERS : 3231 * None 3232 * 3233 * RETURN : int32_t type of status 3234 * NO_ERROR -- success 3235 * none-zero failure code 3236 *==========================================================================*/ 3237 int32_t QCameraPostProcessor::stopCapture() 3238 { 3239 int rc = NO_ERROR; 3240 3241 if (m_parent->isRegularCapture()) { 3242 rc = m_parent->processAPI( 3243 QCAMERA_SM_EVT_STOP_CAPTURE_CHANNEL, 3244 NULL); 3245 } 3246 3247 return rc; 3248 } 3249 3250 /*=========================================================================== 3251 * FUNCTION : getJpegPaddingReq 3252 * 3253 * DESCRIPTION: function to add an entry to exif data 3254 * 3255 * PARAMETERS : 3256 * @padding_info : jpeg specific padding requirement 3257 * 3258 * RETURN : int32_t type of status 3259 * NO_ERROR -- success 3260 * none-zero failure code 3261 *==========================================================================*/ 3262 int32_t QCameraPostProcessor::getJpegPaddingReq(cam_padding_info_t &padding_info) 3263 { 3264 // TODO: hardcode for now, needs to query from mm-jpeg-interface 3265 padding_info.width_padding = CAM_PAD_NONE; 3266 padding_info.height_padding = CAM_PAD_TO_16; 3267 padding_info.plane_padding = CAM_PAD_TO_WORD; 3268 padding_info.offset_info.offset_x = 0; 3269 padding_info.offset_info.offset_y = 0; 3270 return NO_ERROR; 3271 } 3272 3273 /*=========================================================================== 3274 * FUNCTION : setYUVFrameInfo 3275 * 3276 * DESCRIPTION: set Raw YUV frame data info for up-layer 3277 * 3278 * PARAMETERS : 3279 * @frame : process frame received from mm-camera-interface 3280 * 3281 * RETURN : int32_t type of status 3282 * NO_ERROR -- success 3283 * none-zero failure code 3284 * 3285 * NOTE : currently we return frame len, y offset, cbcr offset and frame format 3286 *==========================================================================*/ 3287 int32_t QCameraPostProcessor::setYUVFrameInfo(mm_camera_super_buf_t *recvd_frame) 3288 { 3289 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id); 3290 // check reprocess channel if not found 3291 if (pChannel == NULL) { 3292 for (int8_t i = 0; i < mPPChannelCount; i++) { 3293 if ((mPPChannels[i] != NULL) && 3294 (mPPChannels[i]->getMyHandle() == recvd_frame->ch_id)) { 3295 pChannel = mPPChannels[i]; 3296 break; 3297 } 3298 } 3299 } 3300 3301 if (pChannel == NULL) { 3302 LOGE("No corresponding channel (ch_id = %d) exist, return here", 3303 recvd_frame->ch_id); 3304 return BAD_VALUE; 3305 } 3306 3307 // find snapshot frame 3308 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) { 3309 QCameraStream *pStream = 3310 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id); 3311 if (pStream != NULL) { 3312 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 3313 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { 3314 //get the main frame, use stream info 3315 cam_frame_len_offset_t frame_offset; 3316 cam_dimension_t frame_dim; 3317 cam_format_t frame_fmt; 3318 const char *fmt_string; 3319 pStream->getFrameDimension(frame_dim); 3320 pStream->getFrameOffset(frame_offset); 3321 pStream->getFormat(frame_fmt); 3322 fmt_string = m_parent->mParameters.getFrameFmtString(frame_fmt); 3323 3324 int cbcr_offset = (int32_t)frame_offset.mp[0].len - 3325 frame_dim.width * frame_dim.height; 3326 3327 LOGH("frame width=%d, height=%d, yoff=%d, cbcroff=%d, fmt_string=%s", 3328 frame_dim.width, frame_dim.height, frame_offset.mp[0].offset, cbcr_offset, fmt_string); 3329 return NO_ERROR; 3330 } 3331 } 3332 } 3333 3334 return BAD_VALUE; 3335 } 3336 3337 bool QCameraPostProcessor::matchJobId(void *data, void *, void *match_data) 3338 { 3339 qcamera_jpeg_data_t * job = (qcamera_jpeg_data_t *) data; 3340 uint32_t job_id = *((uint32_t *) match_data); 3341 return job->jobId == job_id; 3342 } 3343 3344 /*=========================================================================== 3345 * FUNCTION : getJpegMemory 3346 * 3347 * DESCRIPTION: buffer allocation function 3348 * to pass to jpeg interface 3349 * 3350 * PARAMETERS : 3351 * @out_buf : buffer descriptor struct 3352 * 3353 * RETURN : int32_t type of status 3354 * NO_ERROR -- success 3355 * none-zero failure code 3356 *==========================================================================*/ 3357 int QCameraPostProcessor::getJpegMemory(omx_jpeg_ouput_buf_t *out_buf) 3358 { 3359 LOGH("Allocating jpeg out buffer of size: %d", out_buf->size); 3360 QCameraPostProcessor *procInst = (QCameraPostProcessor *) out_buf->handle; 3361 camera_memory_t *cam_mem = procInst->m_parent->mGetMemory(out_buf->fd, out_buf->size, 1U, 3362 procInst->m_parent->mCallbackCookie); 3363 out_buf->mem_hdl = cam_mem; 3364 out_buf->vaddr = cam_mem->data; 3365 3366 return 0; 3367 } 3368 3369 /*=========================================================================== 3370 * FUNCTION : releaseJpegMemory 3371 * 3372 * DESCRIPTION: release jpeg memory function 3373 * to pass to jpeg interface, in case of abort 3374 * 3375 * PARAMETERS : 3376 * @out_buf : buffer descriptor struct 3377 * 3378 * RETURN : int32_t type of status 3379 * NO_ERROR -- success 3380 * none-zero failure code 3381 *==========================================================================*/ 3382 int QCameraPostProcessor::releaseJpegMemory(omx_jpeg_ouput_buf_t *out_buf) 3383 { 3384 if (out_buf && out_buf->mem_hdl) { 3385 LOGD("releasing jpeg out buffer of size: %d", out_buf->size); 3386 camera_memory_t *cam_mem = (camera_memory_t*)out_buf->mem_hdl; 3387 cam_mem->release(cam_mem); 3388 out_buf->mem_hdl = NULL; 3389 out_buf->vaddr = NULL; 3390 return NO_ERROR; 3391 } 3392 return -1; 3393 } 3394 3395 /*=========================================================================== 3396 * FUNCTION : QCameraExif 3397 * 3398 * DESCRIPTION: constructor of QCameraExif 3399 * 3400 * PARAMETERS : None 3401 * 3402 * RETURN : None 3403 *==========================================================================*/ 3404 QCameraExif::QCameraExif() 3405 : m_nNumEntries(0) 3406 { 3407 memset(m_Entries, 0, sizeof(m_Entries)); 3408 } 3409 3410 /*=========================================================================== 3411 * FUNCTION : ~QCameraExif 3412 * 3413 * DESCRIPTION: deconstructor of QCameraExif. Will release internal memory ptr. 3414 * 3415 * PARAMETERS : None 3416 * 3417 * RETURN : None 3418 *==========================================================================*/ 3419 QCameraExif::~QCameraExif() 3420 { 3421 for (uint32_t i = 0; i < m_nNumEntries; i++) { 3422 switch (m_Entries[i].tag_entry.type) { 3423 case EXIF_BYTE: 3424 { 3425 if (m_Entries[i].tag_entry.count > 1 && 3426 m_Entries[i].tag_entry.data._bytes != NULL) { 3427 free(m_Entries[i].tag_entry.data._bytes); 3428 m_Entries[i].tag_entry.data._bytes = NULL; 3429 } 3430 } 3431 break; 3432 case EXIF_ASCII: 3433 { 3434 if (m_Entries[i].tag_entry.data._ascii != NULL) { 3435 free(m_Entries[i].tag_entry.data._ascii); 3436 m_Entries[i].tag_entry.data._ascii = NULL; 3437 } 3438 } 3439 break; 3440 case EXIF_SHORT: 3441 { 3442 if (m_Entries[i].tag_entry.count > 1 && 3443 m_Entries[i].tag_entry.data._shorts != NULL) { 3444 free(m_Entries[i].tag_entry.data._shorts); 3445 m_Entries[i].tag_entry.data._shorts = NULL; 3446 } 3447 } 3448 break; 3449 case EXIF_LONG: 3450 { 3451 if (m_Entries[i].tag_entry.count > 1 && 3452 m_Entries[i].tag_entry.data._longs != NULL) { 3453 free(m_Entries[i].tag_entry.data._longs); 3454 m_Entries[i].tag_entry.data._longs = NULL; 3455 } 3456 } 3457 break; 3458 case EXIF_RATIONAL: 3459 { 3460 if (m_Entries[i].tag_entry.count > 1 && 3461 m_Entries[i].tag_entry.data._rats != NULL) { 3462 free(m_Entries[i].tag_entry.data._rats); 3463 m_Entries[i].tag_entry.data._rats = NULL; 3464 } 3465 } 3466 break; 3467 case EXIF_UNDEFINED: 3468 { 3469 if (m_Entries[i].tag_entry.data._undefined != NULL) { 3470 free(m_Entries[i].tag_entry.data._undefined); 3471 m_Entries[i].tag_entry.data._undefined = NULL; 3472 } 3473 } 3474 break; 3475 case EXIF_SLONG: 3476 { 3477 if (m_Entries[i].tag_entry.count > 1 && 3478 m_Entries[i].tag_entry.data._slongs != NULL) { 3479 free(m_Entries[i].tag_entry.data._slongs); 3480 m_Entries[i].tag_entry.data._slongs = NULL; 3481 } 3482 } 3483 break; 3484 case EXIF_SRATIONAL: 3485 { 3486 if (m_Entries[i].tag_entry.count > 1 && 3487 m_Entries[i].tag_entry.data._srats != NULL) { 3488 free(m_Entries[i].tag_entry.data._srats); 3489 m_Entries[i].tag_entry.data._srats = NULL; 3490 } 3491 } 3492 break; 3493 } 3494 } 3495 } 3496 3497 /*=========================================================================== 3498 * FUNCTION : addEntry 3499 * 3500 * DESCRIPTION: function to add an entry to exif data 3501 * 3502 * PARAMETERS : 3503 * @tagid : exif tag ID 3504 * @type : data type 3505 * @count : number of data in uint of its type 3506 * @data : input data ptr 3507 * 3508 * RETURN : int32_t type of status 3509 * NO_ERROR -- success 3510 * none-zero failure code 3511 *==========================================================================*/ 3512 int32_t QCameraExif::addEntry(exif_tag_id_t tagid, 3513 exif_tag_type_t type, 3514 uint32_t count, 3515 void *data) 3516 { 3517 int32_t rc = NO_ERROR; 3518 if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) { 3519 LOGE("Number of entries exceeded limit"); 3520 return NO_MEMORY; 3521 } 3522 3523 m_Entries[m_nNumEntries].tag_id = tagid; 3524 m_Entries[m_nNumEntries].tag_entry.type = type; 3525 m_Entries[m_nNumEntries].tag_entry.count = count; 3526 m_Entries[m_nNumEntries].tag_entry.copy = 1; 3527 switch (type) { 3528 case EXIF_BYTE: 3529 { 3530 if (count > 1) { 3531 uint8_t *values = (uint8_t *)malloc(count); 3532 if (values == NULL) { 3533 LOGE("No memory for byte array"); 3534 rc = NO_MEMORY; 3535 } else { 3536 memcpy(values, data, count); 3537 m_Entries[m_nNumEntries].tag_entry.data._bytes = values; 3538 } 3539 } else { 3540 m_Entries[m_nNumEntries].tag_entry.data._byte = *(uint8_t *)data; 3541 } 3542 } 3543 break; 3544 case EXIF_ASCII: 3545 { 3546 char *str = NULL; 3547 str = (char *)malloc(count + 1); 3548 if (str == NULL) { 3549 LOGE("No memory for ascii string"); 3550 rc = NO_MEMORY; 3551 } else { 3552 memset(str, 0, count + 1); 3553 memcpy(str, data, count); 3554 m_Entries[m_nNumEntries].tag_entry.data._ascii = str; 3555 } 3556 } 3557 break; 3558 case EXIF_SHORT: 3559 { 3560 uint16_t *exif_data = (uint16_t *)data; 3561 if (count > 1) { 3562 uint16_t *values = (uint16_t *)malloc(count * sizeof(uint16_t)); 3563 if (values == NULL) { 3564 LOGE("No memory for short array"); 3565 rc = NO_MEMORY; 3566 } else { 3567 memcpy(values, exif_data, count * sizeof(uint16_t)); 3568 m_Entries[m_nNumEntries].tag_entry.data._shorts = values; 3569 } 3570 } else { 3571 m_Entries[m_nNumEntries].tag_entry.data._short = *(uint16_t *)data; 3572 } 3573 } 3574 break; 3575 case EXIF_LONG: 3576 { 3577 uint32_t *exif_data = (uint32_t *)data; 3578 if (count > 1) { 3579 uint32_t *values = (uint32_t *)malloc(count * sizeof(uint32_t)); 3580 if (values == NULL) { 3581 LOGE("No memory for long array"); 3582 rc = NO_MEMORY; 3583 } else { 3584 memcpy(values, exif_data, count * sizeof(uint32_t)); 3585 m_Entries[m_nNumEntries].tag_entry.data._longs = values; 3586 } 3587 } else { 3588 m_Entries[m_nNumEntries].tag_entry.data._long = *(uint32_t *)data; 3589 } 3590 } 3591 break; 3592 case EXIF_RATIONAL: 3593 { 3594 rat_t *exif_data = (rat_t *)data; 3595 if (count > 1) { 3596 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t)); 3597 if (values == NULL) { 3598 LOGE("No memory for rational array"); 3599 rc = NO_MEMORY; 3600 } else { 3601 memcpy(values, exif_data, count * sizeof(rat_t)); 3602 m_Entries[m_nNumEntries].tag_entry.data._rats = values; 3603 } 3604 } else { 3605 m_Entries[m_nNumEntries].tag_entry.data._rat = *(rat_t *)data; 3606 } 3607 } 3608 break; 3609 case EXIF_UNDEFINED: 3610 { 3611 uint8_t *values = (uint8_t *)malloc(count); 3612 if (values == NULL) { 3613 LOGE("No memory for undefined array"); 3614 rc = NO_MEMORY; 3615 } else { 3616 memcpy(values, data, count); 3617 m_Entries[m_nNumEntries].tag_entry.data._undefined = values; 3618 } 3619 } 3620 break; 3621 case EXIF_SLONG: 3622 { 3623 uint32_t *exif_data = (uint32_t *)data; 3624 if (count > 1) { 3625 int32_t *values = (int32_t *)malloc(count * sizeof(int32_t)); 3626 if (values == NULL) { 3627 LOGE("No memory for signed long array"); 3628 rc = NO_MEMORY; 3629 } else { 3630 memcpy(values, exif_data, count * sizeof(int32_t)); 3631 m_Entries[m_nNumEntries].tag_entry.data._slongs = values; 3632 } 3633 } else { 3634 m_Entries[m_nNumEntries].tag_entry.data._slong = *(int32_t *)data; 3635 } 3636 } 3637 break; 3638 case EXIF_SRATIONAL: 3639 { 3640 srat_t *exif_data = (srat_t *)data; 3641 if (count > 1) { 3642 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t)); 3643 if (values == NULL) { 3644 LOGE("No memory for signed rational array"); 3645 rc = NO_MEMORY; 3646 } else { 3647 memcpy(values, exif_data, count * sizeof(srat_t)); 3648 m_Entries[m_nNumEntries].tag_entry.data._srats = values; 3649 } 3650 } else { 3651 m_Entries[m_nNumEntries].tag_entry.data._srat = *(srat_t *)data; 3652 } 3653 } 3654 break; 3655 } 3656 3657 // Increase number of entries 3658 m_nNumEntries++; 3659 return rc; 3660 } 3661 3662 }; // namespace qcamera 3663