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