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 = -1; 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 mm_camera_buf_def_t *meta_frame = NULL; 765 for (uint32_t i = 0; i < frame->num_bufs; i++) { 766 // look through input superbuf 767 if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 768 meta_frame = frame->bufs[i]; 769 break; 770 } 771 } 772 if (meta_frame != NULL) { 773 //Function to upadte metadata for frame based parameter 774 m_parent->updateMetadata((metadata_buffer_t *)meta_frame->buffer); 775 } 776 777 if (m_parent->needReprocess()) { 778 if ((!m_parent->isLongshotEnabled() && 779 !m_parent->m_stateMachine.isNonZSLCaptureRunning()) || 780 (m_parent->isLongshotEnabled() && 781 m_parent->isCaptureShutterEnabled())) { 782 //play shutter sound 783 m_parent->playShutter(); 784 } 785 786 ATRACE_INT("Camera:Reprocess", 1); 787 CDBG_HIGH("%s: need reprocess", __func__); 788 789 // enqueu to post proc input queue 790 qcamera_pp_request_t *pp_request_job = 791 (qcamera_pp_request_t *)malloc(sizeof(qcamera_pp_request_t)); 792 if (pp_request_job == NULL) { 793 ALOGE("%s: No memory for pproc job", __func__); 794 return NO_MEMORY; 795 } 796 memset(pp_request_job, 0, sizeof(qcamera_pp_request_t)); 797 pp_request_job->src_frame = frame; 798 pp_request_job->src_reproc_frame = frame; 799 pp_request_job->reprocCount = 0; 800 if (m_inputPPQ.enqueue((void *)pp_request_job)) { 801 //avoid sending frame for reprocessing if o/p buffer is not queued to CPP. 802 triggerEvent = validatePostProcess(frame); 803 }else { 804 CDBG_HIGH("%s : Input PP Q is not active!!!", __func__); 805 releaseSuperBuf(frame); 806 free(frame); 807 free(pp_request_job); 808 frame = NULL; 809 pp_request_job = NULL; 810 return NO_ERROR; 811 } 812 if (m_parent->mParameters.isAdvCamFeaturesEnabled() 813 && (meta_frame != NULL)) { 814 m_InputMetadata.add(meta_frame); 815 } 816 } else if (m_parent->mParameters.isNV16PictureFormat() || 817 m_parent->mParameters.isNV21PictureFormat()) { 818 //check if raw frame information is needed. 819 if(m_parent->mParameters.isYUVFrameInfoNeeded()) 820 setYUVFrameInfo(frame); 821 822 processRawData(frame); 823 } else { 824 //play shutter sound 825 if(!m_parent->m_stateMachine.isNonZSLCaptureRunning() && 826 !m_parent->mLongshotEnabled) 827 m_parent->playShutter(); 828 829 CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__); 830 qcamera_jpeg_data_t *jpeg_job = 831 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t)); 832 if (jpeg_job == NULL) { 833 ALOGE("%s: No memory for jpeg job", __func__); 834 return NO_MEMORY; 835 } 836 837 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t)); 838 jpeg_job->src_frame = frame; 839 840 if (meta_frame != NULL) { 841 // fill in meta data frame ptr 842 jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer; 843 } 844 845 // enqueu to jpeg input queue 846 if (!m_inputJpegQ.enqueue((void *)jpeg_job)) { 847 CDBG_HIGH("%s : Input Jpeg Q is not active!!!", __func__); 848 releaseJpegJobData(jpeg_job); 849 free(jpeg_job); 850 jpeg_job = NULL; 851 return NO_ERROR; 852 } 853 } 854 855 if (triggerEvent){ 856 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 857 } 858 859 return NO_ERROR; 860 } 861 862 /*=========================================================================== 863 * FUNCTION : processRawData 864 * 865 * DESCRIPTION: enqueue raw data into dataProc thread 866 * 867 * PARAMETERS : 868 * @frame : process frame received from mm-camera-interface 869 * 870 * RETURN : int32_t type of status 871 * NO_ERROR -- success 872 * none-zero failure code 873 *==========================================================================*/ 874 int32_t QCameraPostProcessor::processRawData(mm_camera_super_buf_t *frame) 875 { 876 if (m_bInited == FALSE) { 877 ALOGE("%s: postproc not initialized yet", __func__); 878 return UNKNOWN_ERROR; 879 } 880 881 // enqueu to raw input queue 882 if (m_inputRawQ.enqueue((void *)frame)) { 883 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 884 } else { 885 CDBG_HIGH("%s : m_inputRawQ is not active!!!", __func__); 886 releaseSuperBuf(frame); 887 free(frame); 888 frame = NULL; 889 } 890 return NO_ERROR; 891 } 892 893 /*=========================================================================== 894 * FUNCTION : processJpegEvt 895 * 896 * DESCRIPTION: process jpeg event from mm-jpeg-interface. 897 * 898 * PARAMETERS : 899 * @evt : payload of jpeg event, including information about jpeg encoding 900 * status, jpeg size and so on. 901 * 902 * RETURN : int32_t type of status 903 * NO_ERROR -- success 904 * none-zero failure code 905 * 906 * NOTE : This event will also trigger DataProc thread to move to next job 907 * processing (i.e., send a new jpeg encoding job to mm-jpeg-interface 908 * if there is any pending job in jpeg input queue) 909 *==========================================================================*/ 910 int32_t QCameraPostProcessor::processJpegEvt(qcamera_jpeg_evt_payload_t *evt) 911 { 912 if (m_bInited == FALSE) { 913 ALOGE("%s: postproc not initialized yet", __func__); 914 return UNKNOWN_ERROR; 915 } 916 917 int32_t rc = NO_ERROR; 918 camera_memory_t *jpeg_mem = NULL; 919 omx_jpeg_ouput_buf_t *jpeg_out = NULL; 920 921 if (mUseSaveProc && m_parent->isLongshotEnabled()) { 922 qcamera_jpeg_evt_payload_t *saveData = ( qcamera_jpeg_evt_payload_t * ) malloc(sizeof(qcamera_jpeg_evt_payload_t)); 923 if ( NULL == saveData ) { 924 ALOGE("%s: Can not allocate save data message!", __func__); 925 return NO_MEMORY; 926 } 927 *saveData = *evt; 928 if (m_inputSaveQ.enqueue((void *) saveData)) { 929 m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 930 } else { 931 CDBG("%s : m_inputSaveQ PP Q is not active!!!", __func__); 932 free(saveData); 933 saveData = NULL; 934 return rc; 935 } 936 } else { 937 // Release jpeg job data 938 m_ongoingJpegQ.flushNodes(matchJobId, (void*)&evt->jobId); 939 940 if (m_inputPPQ.getCurrentSize() > 0) { 941 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 942 } 943 CDBG_HIGH("[KPI Perf] %s : jpeg job %d", __func__, evt->jobId); 944 945 if ((false == m_parent->m_bIntJpegEvtPending) && 946 (m_parent->mDataCb == NULL || 947 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) == 0 )) { 948 CDBG_HIGH("%s: No dataCB or CAMERA_MSG_COMPRESSED_IMAGE not enabled", 949 __func__); 950 rc = NO_ERROR; 951 goto end; 952 } 953 954 if(evt->status == JPEG_JOB_STATUS_ERROR) { 955 ALOGE("%s: Error event handled from jpeg, status = %d", 956 __func__, evt->status); 957 rc = FAILED_TRANSACTION; 958 goto end; 959 } 960 961 m_parent->dumpJpegToFile(evt->out_data.buf_vaddr, 962 evt->out_data.buf_filled_len, 963 evt->jobId); 964 CDBG_HIGH("%s: Dump jpeg_size=%d", __func__, evt->out_data.buf_filled_len); 965 966 if(true == m_parent->m_bIntJpegEvtPending) { 967 //Sending JPEG snapshot taken notification to HAL 968 pthread_mutex_lock(&m_parent->m_int_lock); 969 pthread_cond_signal(&m_parent->m_int_cond); 970 pthread_mutex_unlock(&m_parent->m_int_lock); 971 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 972 return rc; 973 } 974 975 if (!mJpegMemOpt) { 976 // alloc jpeg memory to pass to upper layer 977 jpeg_mem = m_parent->mGetMemory(-1, evt->out_data.buf_filled_len, 978 1, m_parent->mCallbackCookie); 979 if (NULL == jpeg_mem) { 980 rc = NO_MEMORY; 981 ALOGE("%s : getMemory for jpeg, ret = NO_MEMORY", __func__); 982 goto end; 983 } 984 memcpy(jpeg_mem->data, evt->out_data.buf_vaddr, evt->out_data.buf_filled_len); 985 } else { 986 jpeg_out = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr; 987 jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl; 988 } 989 990 CDBG_HIGH("%s : Calling upperlayer callback to store JPEG image", __func__); 991 qcamera_release_data_t release_data; 992 memset(&release_data, 0, sizeof(qcamera_release_data_t)); 993 release_data.data = jpeg_mem; 994 CDBG_HIGH("[KPI Perf] %s: PROFILE_JPEG_CB ",__func__); 995 rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 996 jpeg_mem, 997 0, 998 NULL, 999 &release_data); 1000 m_parent->setOutputImageCount(m_parent->getOutputImageCount() + 1); 1001 1002 end: 1003 if (rc != NO_ERROR) { 1004 // send error msg to upper layer 1005 sendEvtNotify(CAMERA_MSG_ERROR, 1006 UNKNOWN_ERROR, 1007 0); 1008 1009 if (NULL != jpeg_mem) { 1010 jpeg_mem->release(jpeg_mem); 1011 jpeg_mem = NULL; 1012 } 1013 } 1014 1015 /* check whether to send callback for depth map */ 1016 if (m_parent->mParameters.isUbiRefocus() && 1017 (m_parent->getOutputImageCount() + 1 == 1018 m_parent->mParameters.getRefocusOutputCount())) { 1019 m_parent->setOutputImageCount(m_parent->getOutputImageCount() + 1); 1020 1021 jpeg_mem = m_DataMem; 1022 release_data.data = jpeg_mem; 1023 m_DataMem = NULL; 1024 CDBG_HIGH("[KPI Perf] %s: send jpeg callback for depthmap ",__func__); 1025 rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 1026 jpeg_mem, 1027 0, 1028 NULL, 1029 &release_data); 1030 if (rc != NO_ERROR) { 1031 // send error msg to upper layer 1032 sendEvtNotify(CAMERA_MSG_ERROR, 1033 UNKNOWN_ERROR, 1034 0); 1035 if (NULL != jpeg_mem) { 1036 jpeg_mem->release(jpeg_mem); 1037 jpeg_mem = NULL; 1038 } 1039 } 1040 } 1041 } 1042 1043 // wait up data proc thread to do next job, 1044 // if previous request is blocked due to ongoing jpeg job 1045 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 1046 1047 return rc; 1048 } 1049 1050 /*=========================================================================== 1051 * FUNCTION : processPPData 1052 * 1053 * DESCRIPTION: process received frame after reprocess. 1054 * 1055 * PARAMETERS : 1056 * @frame : received frame from reprocess channel. 1057 * 1058 * RETURN : int32_t type of status 1059 * NO_ERROR -- success 1060 * none-zero failure code 1061 * 1062 * NOTE : The frame after reprocess need to send to jpeg encoding. 1063 *==========================================================================*/ 1064 int32_t QCameraPostProcessor::processPPData(mm_camera_super_buf_t *frame) 1065 { 1066 bool triggerEvent = TRUE; 1067 1068 bool needSuperBufMatch = m_parent->mParameters.generateThumbFromMain(); 1069 if (m_bInited == FALSE) { 1070 ALOGE("%s: postproc not initialized yet", __func__); 1071 return UNKNOWN_ERROR; 1072 } 1073 1074 qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue(); 1075 if (NULL == job) { 1076 ALOGE("%s: Cannot find reprocess job", __func__); 1077 return BAD_VALUE; 1078 } 1079 1080 if (!needSuperBufMatch && (job->src_frame == NULL 1081 || job->src_reproc_frame == NULL) ) { 1082 ALOGE("%s: Invalid reprocess job", __func__); 1083 return BAD_VALUE; 1084 } 1085 1086 if (!needSuperBufMatch && (m_parent->mParameters.isNV16PictureFormat() || 1087 m_parent->mParameters.isNV21PictureFormat())) { 1088 releaseOngoingPPData(job, this); 1089 free(job); 1090 1091 if(m_parent->mParameters.isYUVFrameInfoNeeded()) 1092 setYUVFrameInfo(frame); 1093 return processRawData(frame); 1094 } 1095 if (m_parent->isLongshotEnabled() && 1096 !m_parent->isCaptureShutterEnabled()) { 1097 // play shutter sound for longshot 1098 // after reprocess is done 1099 // TODO: Move this after CAC done event 1100 m_parent->playShutter(); 1101 } 1102 1103 int8_t mCurReprocCount = job->reprocCount; 1104 if ( mCurReprocCount > 1 ) { 1105 //In case of pp 2nd pass, we can release input of 2nd pass 1106 releaseSuperBuf(job->src_frame); 1107 free(job->src_frame); 1108 job->src_frame = NULL; 1109 } 1110 1111 CDBG("%s: mCurReprocCount = %d mTotalNumReproc = %d", 1112 __func__, mCurReprocCount, mTotalNumReproc); 1113 if (mCurReprocCount < mTotalNumReproc) { 1114 //More pp pass needed. Push frame back to pp queue. 1115 qcamera_pp_request_t *pp_request_job = 1116 (qcamera_pp_request_t *)malloc(sizeof(qcamera_pp_request_t)); 1117 if (pp_request_job == NULL) { 1118 ALOGE("%s: No memory for pproc job", __func__); 1119 return NO_MEMORY; 1120 } 1121 memset(pp_request_job, 0, sizeof(qcamera_pp_request_t)); 1122 pp_request_job->src_frame = frame; 1123 pp_request_job->src_reproc_frame = job->src_reproc_frame; 1124 pp_request_job->reprocCount = mCurReprocCount; 1125 // enqueu to post proc input queue 1126 if (m_inputPPQ.enqueue((void *)pp_request_job)) { 1127 triggerEvent = validatePostProcess(frame); 1128 } else { 1129 CDBG_HIGH("%s : m_input PP Q is not active!!!", __func__); 1130 releasePPInputData(pp_request_job,this); 1131 free(pp_request_job); 1132 pp_request_job = NULL; 1133 triggerEvent = FALSE; 1134 } 1135 } else { 1136 //Done with post processing. Send frame to Jpeg 1137 qcamera_jpeg_data_t *jpeg_job = 1138 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t)); 1139 if (jpeg_job == NULL) { 1140 ALOGE("%s: No memory for jpeg job", __func__); 1141 return NO_MEMORY; 1142 } 1143 1144 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t)); 1145 jpeg_job->src_frame = frame; 1146 jpeg_job->src_reproc_frame = job ? job->src_reproc_frame : NULL; 1147 jpeg_job->src_reproc_bufs = job ? job->src_reproc_bufs : NULL; 1148 jpeg_job->reproc_frame_release = job ? job->reproc_frame_release : false; 1149 1150 // find meta data frame 1151 mm_camera_buf_def_t *meta_frame = NULL; 1152 if (m_parent->mParameters.isAdvCamFeaturesEnabled()) { 1153 size_t meta_idx = m_parent->mParameters.getExifBufIndex(m_PPindex); 1154 if (m_InputMetadata.size() >= (meta_idx + 1)) { 1155 meta_frame = m_InputMetadata.itemAt(meta_idx); 1156 } else { 1157 ALOGE("%s: Input metadata vector contains %d entries, index required %d", 1158 __func__, m_InputMetadata.size(), meta_idx); 1159 } 1160 m_PPindex++; 1161 } else { 1162 for (uint32_t i = 0; job && job->src_reproc_frame && 1163 (i < job->src_reproc_frame->num_bufs); i++) { 1164 // look through input superbuf 1165 if (job->src_reproc_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 1166 meta_frame = job->src_reproc_frame->bufs[i]; 1167 break; 1168 } 1169 } 1170 1171 if (meta_frame == NULL) { 1172 // look through reprocess superbuf 1173 for (uint32_t i = 0; i < frame->num_bufs; i++) { 1174 if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 1175 meta_frame = frame->bufs[i]; 1176 break; 1177 } 1178 } 1179 } 1180 } 1181 if (meta_frame != NULL) { 1182 // fill in meta data frame ptr 1183 jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer; 1184 } 1185 1186 // enqueu reprocessed frame to jpeg input queue 1187 if (m_inputJpegQ.enqueue((void *)jpeg_job)) { 1188 if (m_parent->isLongshotEnabled()) { 1189 triggerEvent = validatePostProcess(frame); 1190 } 1191 } else { 1192 CDBG_HIGH("%s : Input Jpeg Q is not active!!!", __func__); 1193 releaseJpegJobData(jpeg_job); 1194 free(jpeg_job); 1195 jpeg_job = NULL; 1196 triggerEvent = FALSE; 1197 } 1198 } 1199 1200 // free pp job buf 1201 if (job) { 1202 free(job); 1203 } 1204 1205 ALOGD("%s: %d] ", __func__, __LINE__); 1206 // wait up data proc thread 1207 1208 if (triggerEvent) { 1209 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 1210 } 1211 1212 return NO_ERROR; 1213 } 1214 1215 /*=========================================================================== 1216 * FUNCTION : findJpegJobByJobId 1217 * 1218 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID 1219 * 1220 * PARAMETERS : 1221 * @jobId : job Id of the job 1222 * 1223 * RETURN : ptr to a jpeg job struct. NULL if not found. 1224 * 1225 * NOTE : Currently only one job is sending to mm-jpeg-interface for jpeg 1226 * encoding. Therefore simply dequeue from the ongoing Jpeg Queue 1227 * will serve the purpose to find the jpeg job. 1228 *==========================================================================*/ 1229 qcamera_jpeg_data_t *QCameraPostProcessor::findJpegJobByJobId(uint32_t jobId) 1230 { 1231 qcamera_jpeg_data_t * job = NULL; 1232 if (jobId == 0) { 1233 ALOGE("%s: not a valid jpeg jobId", __func__); 1234 return NULL; 1235 } 1236 1237 // currely only one jpeg job ongoing, so simply dequeue the head 1238 job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue(); 1239 return job; 1240 } 1241 1242 /*=========================================================================== 1243 * FUNCTION : releasePPInputData 1244 * 1245 * DESCRIPTION: callback function to release post process input data node 1246 * 1247 * PARAMETERS : 1248 * @data : ptr to post process input data 1249 * @user_data : user data ptr (QCameraReprocessor) 1250 * 1251 * RETURN : None 1252 *==========================================================================*/ 1253 void QCameraPostProcessor::releasePPInputData(void *data, void *user_data) 1254 { 1255 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data; 1256 if (NULL != pme) { 1257 qcamera_pp_request_t *pp_job = (qcamera_pp_request_t *)data; 1258 if (NULL != pp_job->src_frame) { 1259 pme->releaseSuperBuf(pp_job->src_frame); 1260 if (pp_job->src_frame == pp_job->src_reproc_frame) 1261 pp_job->src_reproc_frame = NULL; 1262 free(pp_job->src_frame); 1263 pp_job->src_frame = NULL; 1264 } 1265 if (NULL != pp_job->src_reproc_frame) { 1266 pme->releaseSuperBuf(pp_job->src_reproc_frame); 1267 free(pp_job->src_reproc_frame); 1268 pp_job->src_reproc_frame = NULL; 1269 } 1270 pp_job->reprocCount = 0; 1271 } 1272 } 1273 1274 /*=========================================================================== 1275 * FUNCTION : releaseJpegData 1276 * 1277 * DESCRIPTION: callback function to release jpeg job node 1278 * 1279 * PARAMETERS : 1280 * @data : ptr to ongoing jpeg job data 1281 * @user_data : user data ptr (QCameraReprocessor) 1282 * 1283 * RETURN : None 1284 *==========================================================================*/ 1285 void QCameraPostProcessor::releaseJpegData(void *data, void *user_data) 1286 { 1287 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data; 1288 if (NULL != pme) { 1289 pme->releaseJpegJobData((qcamera_jpeg_data_t *)data); 1290 CDBG_HIGH("%s : Rleased job ID %u", __func__, 1291 ((qcamera_jpeg_data_t *)data)->jobId); 1292 } 1293 } 1294 1295 /*=========================================================================== 1296 * FUNCTION : releaseOngoingPPData 1297 * 1298 * DESCRIPTION: callback function to release ongoing postprocess job node 1299 * 1300 * PARAMETERS : 1301 * @data : ptr to onging postprocess job 1302 * @user_data : user data ptr (QCameraReprocessor) 1303 * 1304 * RETURN : None 1305 *==========================================================================*/ 1306 void QCameraPostProcessor::releaseOngoingPPData(void *data, void *user_data) 1307 { 1308 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data; 1309 if (NULL != pme) { 1310 qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data; 1311 if (NULL != pp_job->src_frame) { 1312 if (!pp_job->reproc_frame_release) { 1313 pme->releaseSuperBuf(pp_job->src_frame); 1314 } 1315 if (pp_job->src_frame == pp_job->src_reproc_frame) 1316 pp_job->src_reproc_frame = NULL; 1317 1318 free(pp_job->src_frame); 1319 pp_job->src_frame = NULL; 1320 } 1321 if (NULL != pp_job->src_reproc_frame) { 1322 pme->releaseSuperBuf(pp_job->src_reproc_frame); 1323 free(pp_job->src_reproc_frame); 1324 pp_job->src_reproc_frame = NULL; 1325 } 1326 pp_job->reprocCount = 0; 1327 } 1328 } 1329 1330 /*=========================================================================== 1331 * FUNCTION : releaseNotifyData 1332 * 1333 * DESCRIPTION: function to release internal resources in notify data struct 1334 * 1335 * PARAMETERS : 1336 * @user_data : ptr user data 1337 * @cookie : callback cookie 1338 * @cb_status : callback status 1339 * 1340 * RETURN : None 1341 * 1342 * NOTE : deallocate jpeg heap memory if it's not NULL 1343 *==========================================================================*/ 1344 void QCameraPostProcessor::releaseNotifyData(void *user_data, 1345 void *cookie, 1346 int32_t cb_status) 1347 { 1348 qcamera_data_argm_t *app_cb = ( qcamera_data_argm_t * ) user_data; 1349 QCameraPostProcessor *postProc = ( QCameraPostProcessor * ) cookie; 1350 if ( ( NULL != app_cb ) && ( NULL != postProc ) ) { 1351 1352 if ( postProc->mUseSaveProc && 1353 app_cb->release_data.unlinkFile && 1354 ( NO_ERROR != cb_status ) ) { 1355 1356 String8 unlinkPath((const char *) app_cb->release_data.data->data, 1357 app_cb->release_data.data->size); 1358 int rc = unlink(unlinkPath.string()); 1359 CDBG_HIGH("%s : Unlinking stored file rc = %d", 1360 __func__, 1361 rc); 1362 } 1363 1364 if (app_cb && NULL != app_cb->release_data.data) { 1365 app_cb->release_data.data->release(app_cb->release_data.data); 1366 app_cb->release_data.data = NULL; 1367 } 1368 if (app_cb && NULL != app_cb->release_data.frame) { 1369 postProc->releaseSuperBuf(app_cb->release_data.frame); 1370 free(app_cb->release_data.frame); 1371 app_cb->release_data.frame = NULL; 1372 } 1373 if (app_cb && NULL != app_cb->release_data.streamBufs) { 1374 app_cb->release_data.streamBufs->deallocate(); 1375 delete app_cb->release_data.streamBufs; 1376 app_cb->release_data.streamBufs = NULL; 1377 } 1378 free(app_cb); 1379 } 1380 } 1381 1382 /*=========================================================================== 1383 * FUNCTION : releaseSuperBuf 1384 * 1385 * DESCRIPTION: function to release a superbuf frame by returning back to kernel 1386 * 1387 * PARAMETERS : 1388 * @super_buf : ptr to the superbuf frame 1389 * 1390 * RETURN : None 1391 *==========================================================================*/ 1392 void QCameraPostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf) 1393 { 1394 QCameraChannel *pChannel = NULL; 1395 1396 if (NULL != super_buf) { 1397 pChannel = m_parent->getChannelByHandle(super_buf->ch_id); 1398 1399 if ( NULL == pChannel ) { 1400 for (int8_t i = 0; i < mTotalNumReproc; i++) { 1401 if ((mPPChannels[i] != NULL) && 1402 (mPPChannels[i]->getMyHandle() == super_buf->ch_id)) { 1403 pChannel = mPPChannels[i]; 1404 break; 1405 } 1406 } 1407 } 1408 1409 if (pChannel != NULL) { 1410 pChannel->bufDone(super_buf); 1411 } else { 1412 ALOGE(" %s : Channel id %d not found!!", 1413 __func__, 1414 super_buf->ch_id); 1415 } 1416 } 1417 } 1418 1419 /*=========================================================================== 1420 * FUNCTION : releaseJpegJobData 1421 * 1422 * DESCRIPTION: function to release internal resources in jpeg job struct 1423 * 1424 * PARAMETERS : 1425 * @job : ptr to jpeg job struct 1426 * 1427 * RETURN : None 1428 * 1429 * NOTE : original source frame need to be queued back to kernel for 1430 * future use. Output buf of jpeg job need to be released since 1431 * it's allocated for each job. Exif object need to be deleted. 1432 *==========================================================================*/ 1433 void QCameraPostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job) 1434 { 1435 CDBG("%s: E", __func__); 1436 if (NULL != job) { 1437 if (NULL != job->src_reproc_frame) { 1438 if (!job->reproc_frame_release) { 1439 releaseSuperBuf(job->src_reproc_frame); 1440 } 1441 free(job->src_reproc_frame); 1442 job->src_reproc_frame = NULL; 1443 } 1444 1445 if (NULL != job->src_frame) { 1446 releaseSuperBuf(job->src_frame); 1447 free(job->src_frame); 1448 job->src_frame = NULL; 1449 } 1450 1451 if (NULL != job->pJpegExifObj) { 1452 delete job->pJpegExifObj; 1453 job->pJpegExifObj = NULL; 1454 } 1455 1456 if (NULL != job->src_reproc_bufs) { 1457 delete [] job->src_reproc_bufs; 1458 } 1459 1460 } 1461 CDBG("%s: X", __func__); 1462 } 1463 1464 /*=========================================================================== 1465 * FUNCTION : releaseSaveJobData 1466 * 1467 * DESCRIPTION: function to release internal resources in store jobs 1468 * 1469 * PARAMETERS : 1470 * @job : ptr to save job struct 1471 * 1472 * RETURN : None 1473 * 1474 *==========================================================================*/ 1475 void QCameraPostProcessor::releaseSaveJobData(void *data, void *user_data) 1476 { 1477 CDBG("%s: E", __func__); 1478 1479 QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data; 1480 if (NULL == pme) { 1481 ALOGE("%s: Invalid postproc handle", __func__); 1482 return; 1483 } 1484 1485 qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) data; 1486 if (job_data == NULL) { 1487 ALOGE("%s: Invalid jpeg event data", __func__); 1488 return; 1489 } 1490 1491 // find job by jobId 1492 qcamera_jpeg_data_t *job = pme->findJpegJobByJobId(job_data->jobId); 1493 1494 if (NULL != job) { 1495 pme->releaseJpegJobData(job); 1496 free(job); 1497 } else { 1498 ALOGE("%s : Invalid jpeg job", __func__); 1499 } 1500 1501 CDBG("%s: X", __func__); 1502 } 1503 1504 /*=========================================================================== 1505 * FUNCTION : releaseRawData 1506 * 1507 * DESCRIPTION: function to release internal resources in store jobs 1508 * 1509 * PARAMETERS : 1510 * @job : ptr to save job struct 1511 * 1512 * RETURN : None 1513 * 1514 *==========================================================================*/ 1515 void QCameraPostProcessor::releaseRawData(void *data, void *user_data) 1516 { 1517 CDBG("%s: E", __func__); 1518 1519 QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data; 1520 if (NULL == pme) { 1521 ALOGE("%s: Invalid postproc handle", __func__); 1522 return; 1523 } 1524 mm_camera_super_buf_t *super_buf = (mm_camera_super_buf_t *) data; 1525 pme->releaseSuperBuf(super_buf); 1526 1527 CDBG("%s: X", __func__); 1528 } 1529 1530 1531 /*=========================================================================== 1532 * FUNCTION : getColorfmtFromImgFmt 1533 * 1534 * DESCRIPTION: function to return jpeg color format based on its image format 1535 * 1536 * PARAMETERS : 1537 * @img_fmt : image format 1538 * 1539 * RETURN : jpeg color format that can be understandable by omx lib 1540 *==========================================================================*/ 1541 mm_jpeg_color_format QCameraPostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt) 1542 { 1543 switch (img_fmt) { 1544 case CAM_FORMAT_YUV_420_NV21: 1545 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 1546 case CAM_FORMAT_YUV_420_NV21_ADRENO: 1547 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 1548 case CAM_FORMAT_YUV_420_NV12: 1549 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 1550 case CAM_FORMAT_YUV_420_YV12: 1551 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 1552 case CAM_FORMAT_YUV_422_NV61: 1553 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1; 1554 case CAM_FORMAT_YUV_422_NV16: 1555 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1; 1556 default: 1557 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 1558 } 1559 } 1560 1561 /*=========================================================================== 1562 * FUNCTION : getJpegImgTypeFromImgFmt 1563 * 1564 * DESCRIPTION: function to return jpeg encode image type based on its image format 1565 * 1566 * PARAMETERS : 1567 * @img_fmt : image format 1568 * 1569 * RETURN : return jpeg source image format (YUV or Bitstream) 1570 *==========================================================================*/ 1571 mm_jpeg_format_t QCameraPostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt) 1572 { 1573 switch (img_fmt) { 1574 case CAM_FORMAT_YUV_420_NV21: 1575 case CAM_FORMAT_YUV_420_NV21_ADRENO: 1576 case CAM_FORMAT_YUV_420_NV12: 1577 case CAM_FORMAT_YUV_420_YV12: 1578 case CAM_FORMAT_YUV_422_NV61: 1579 case CAM_FORMAT_YUV_422_NV16: 1580 return MM_JPEG_FMT_YUV; 1581 default: 1582 return MM_JPEG_FMT_YUV; 1583 } 1584 } 1585 1586 /*=========================================================================== 1587 * FUNCTION : queryStreams 1588 * 1589 * DESCRIPTION: utility method for retrieving main, thumbnail and reprocess 1590 * streams and frame from bundled super buffer 1591 * 1592 * PARAMETERS : 1593 * @main : ptr to main stream if present 1594 * @thumb : ptr to thumbnail stream if present 1595 * @reproc : ptr to reprocess stream if present 1596 * @main_image : ptr to main image if present 1597 * @thumb_image: ptr to thumbnail image if present 1598 * @frame : bundled super buffer 1599 * @reproc_frame : bundled source frame buffer 1600 * 1601 * RETURN : int32_t type of status 1602 * NO_ERROR -- success 1603 * none-zero failure code 1604 *==========================================================================*/ 1605 int32_t QCameraPostProcessor::queryStreams(QCameraStream **main, 1606 QCameraStream **thumb, 1607 QCameraStream **reproc, 1608 mm_camera_buf_def_t **main_image, 1609 mm_camera_buf_def_t **thumb_image, 1610 mm_camera_super_buf_t *frame, 1611 mm_camera_super_buf_t *reproc_frame) 1612 { 1613 if (NULL == frame) { 1614 return NO_INIT; 1615 } 1616 1617 QCameraChannel *pChannel = m_parent->getChannelByHandle(frame->ch_id); 1618 // check reprocess channel if not found 1619 if (pChannel == NULL) { 1620 for (int8_t i = 0; i < mTotalNumReproc; i++) { 1621 if ((mPPChannels[i] != NULL) && 1622 (mPPChannels[i]->getMyHandle() == frame->ch_id)) { 1623 pChannel = mPPChannels[i]; 1624 break; 1625 } 1626 } 1627 } 1628 if (pChannel == NULL) { 1629 ALOGD("%s: No corresponding channel (ch_id = %d) exist, return here", 1630 __func__, frame->ch_id); 1631 return BAD_VALUE; 1632 } 1633 1634 // Use snapshot stream to create thumbnail if snapshot and preview 1635 // flip settings doesn't match in ZSL mode. 1636 bool thumb_stream_needed = ((!m_parent->isZSLMode() || 1637 (m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT) == 1638 m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_PREVIEW))) && 1639 !m_parent->mParameters.generateThumbFromMain()); 1640 1641 *main = *thumb = *reproc = NULL; 1642 *main_image = *thumb_image = NULL; 1643 // find snapshot frame and thumnail frame 1644 for (uint32_t i = 0; i < frame->num_bufs; i++) { 1645 QCameraStream *pStream = 1646 pChannel->getStreamByHandle(frame->bufs[i]->stream_id); 1647 if (pStream != NULL) { 1648 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 1649 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 1650 (m_parent->mParameters.getofflineRAW() && 1651 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW))) { 1652 *main= pStream; 1653 *main_image = frame->bufs[i]; 1654 } else if (thumb_stream_needed && 1655 (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 1656 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 1657 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) || 1658 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW))) { 1659 *thumb = pStream; 1660 *thumb_image = frame->bufs[i]; 1661 } 1662 if (pStream->isTypeOf(CAM_STREAM_TYPE_OFFLINE_PROC) ) { 1663 *reproc = pStream; 1664 } 1665 } 1666 } 1667 1668 if (thumb_stream_needed && *thumb_image == NULL && reproc_frame != NULL) { 1669 QCameraChannel *pSrcReprocChannel = NULL; 1670 pSrcReprocChannel = m_parent->getChannelByHandle(reproc_frame->ch_id); 1671 if (pSrcReprocChannel != NULL) { 1672 // find thumbnail frame 1673 for (uint32_t i = 0; i < reproc_frame->num_bufs; i++) { 1674 QCameraStream *pStream = 1675 pSrcReprocChannel->getStreamByHandle( 1676 reproc_frame->bufs[i]->stream_id); 1677 if (pStream != NULL) { 1678 if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 1679 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW)) { 1680 *thumb = pStream; 1681 *thumb_image = reproc_frame->bufs[i]; 1682 } 1683 } 1684 } 1685 } 1686 } 1687 1688 return NO_ERROR; 1689 } 1690 1691 /*=========================================================================== 1692 * FUNCTION : syncStreamParams 1693 * 1694 * DESCRIPTION: Query the runtime parameters of all streams included 1695 * in the main and reprocessed frames 1696 * 1697 * PARAMETERS : 1698 * @frame : Main image super buffer 1699 * @reproc_frame : Image supper buffer that got processed 1700 * 1701 * RETURN : int32_t type of status 1702 * NO_ERROR -- success 1703 * none-zero failure code 1704 *==========================================================================*/ 1705 int32_t QCameraPostProcessor::syncStreamParams(mm_camera_super_buf_t *frame, 1706 mm_camera_super_buf_t *reproc_frame) 1707 { 1708 QCameraStream *reproc_stream = NULL; 1709 QCameraStream *main_stream = NULL; 1710 QCameraStream *thumb_stream = NULL; 1711 mm_camera_buf_def_t *main_frame = NULL; 1712 mm_camera_buf_def_t *thumb_frame = NULL; 1713 int32_t ret = NO_ERROR; 1714 1715 ret = queryStreams(&main_stream, 1716 &thumb_stream, 1717 &reproc_stream, 1718 &main_frame, 1719 &thumb_frame, 1720 frame, 1721 reproc_frame); 1722 if (NO_ERROR != ret) { 1723 ALOGE("%s : Camera streams query from input frames failed %d", 1724 __func__, 1725 ret); 1726 return ret; 1727 } 1728 1729 if (NULL != main_stream) { 1730 ret = main_stream->syncRuntimeParams(); 1731 if (NO_ERROR != ret) { 1732 ALOGE("%s : Syncing of main stream runtime parameters failed %d", 1733 __func__, 1734 ret); 1735 return ret; 1736 } 1737 } 1738 1739 if (NULL != thumb_stream) { 1740 ret = thumb_stream->syncRuntimeParams(); 1741 if (NO_ERROR != ret) { 1742 ALOGE("%s : Syncing of thumb stream runtime parameters failed %d", 1743 __func__, 1744 ret); 1745 return ret; 1746 } 1747 } 1748 1749 if ((NULL != reproc_stream) && (reproc_stream != main_stream)) { 1750 ret = reproc_stream->syncRuntimeParams(); 1751 if (NO_ERROR != ret) { 1752 ALOGE("%s : Syncing of reproc stream runtime parameters failed %d", 1753 __func__, 1754 ret); 1755 return ret; 1756 } 1757 } 1758 1759 return ret; 1760 } 1761 1762 /*=========================================================================== 1763 * FUNCTION : encodeData 1764 * 1765 * DESCRIPTION: function to prepare encoding job information and send to 1766 * mm-jpeg-interface to do the encoding job 1767 * 1768 * PARAMETERS : 1769 * @jpeg_job_data : ptr to a struct saving job related information 1770 * @needNewSess : flag to indicate if a new jpeg encoding session need 1771 * to be created. After creation, this flag will be toggled 1772 * 1773 * RETURN : int32_t type of status 1774 * NO_ERROR -- success 1775 * none-zero failure code 1776 *==========================================================================*/ 1777 int32_t QCameraPostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data, 1778 uint8_t &needNewSess) 1779 { 1780 CDBG("%s : E", __func__); 1781 int32_t ret = NO_ERROR; 1782 mm_jpeg_job_t jpg_job; 1783 uint32_t jobId = 0; 1784 QCameraStream *reproc_stream = NULL; 1785 QCameraStream *main_stream = NULL; 1786 mm_camera_buf_def_t *main_frame = NULL; 1787 QCameraStream *thumb_stream = NULL; 1788 mm_camera_buf_def_t *thumb_frame = NULL; 1789 mm_camera_super_buf_t *recvd_frame = jpeg_job_data->src_frame; 1790 cam_rect_t crop; 1791 cam_stream_parm_buffer_t param; 1792 cam_stream_img_prop_t imgProp; 1793 1794 // find channel 1795 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id); 1796 // check reprocess channel if not found 1797 if (pChannel == NULL) { 1798 for (int8_t i = 0; i < mTotalNumReproc; i++) { 1799 if ((mPPChannels[i] != NULL) && 1800 (mPPChannels[i]->getMyHandle() == recvd_frame->ch_id)) { 1801 pChannel = mPPChannels[i]; 1802 break; 1803 } 1804 } 1805 } 1806 1807 if (pChannel == NULL) { 1808 ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here", 1809 __func__, __LINE__, recvd_frame->ch_id); 1810 return BAD_VALUE; 1811 } 1812 1813 const uint32_t jpeg_rotation = m_parent->mParameters.getJpegRotation(); 1814 1815 ret = queryStreams(&main_stream, 1816 &thumb_stream, 1817 &reproc_stream, 1818 &main_frame, 1819 &thumb_frame, 1820 recvd_frame, 1821 jpeg_job_data->src_reproc_frame); 1822 if (NO_ERROR != ret) { 1823 return ret; 1824 } 1825 1826 if(NULL == main_frame){ 1827 ALOGE("%s : Main frame is NULL", __func__); 1828 return BAD_VALUE; 1829 } 1830 1831 if(NULL == thumb_frame){ 1832 CDBG("%s : Thumbnail frame does not exist", __func__); 1833 } 1834 1835 QCameraMemory *memObj = (QCameraMemory *)main_frame->mem_info; 1836 if (NULL == memObj) { 1837 ALOGE("%s : Memeory Obj of main frame is NULL", __func__); 1838 return NO_MEMORY; 1839 } 1840 1841 // dump snapshot frame if enabled 1842 m_parent->dumpFrameToFile(main_stream, main_frame, QCAMERA_DUMP_FRM_SNAPSHOT); 1843 1844 // send upperlayer callback for raw image 1845 camera_memory_t *mem = memObj->getMemory(main_frame->buf_idx, false); 1846 if (NULL != m_parent->mDataCb && 1847 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) { 1848 qcamera_callback_argm_t cbArg; 1849 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 1850 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 1851 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE; 1852 cbArg.data = mem; 1853 cbArg.index = 1; 1854 m_parent->m_cbNotifier.notifyCallback(cbArg); 1855 } 1856 if (NULL != m_parent->mNotifyCb && 1857 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) { 1858 qcamera_callback_argm_t cbArg; 1859 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 1860 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; 1861 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY; 1862 cbArg.ext1 = 0; 1863 cbArg.ext2 = 0; 1864 m_parent->m_cbNotifier.notifyCallback(cbArg); 1865 } 1866 1867 if (mJpegClientHandle <= 0) { 1868 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__); 1869 return UNKNOWN_ERROR; 1870 } 1871 1872 if (needNewSess) { 1873 // create jpeg encoding session 1874 mm_jpeg_encode_params_t encodeParam; 1875 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t)); 1876 ret = getJpegEncodingConfig(encodeParam, main_stream, thumb_stream); 1877 if (ret != NO_ERROR) { 1878 ALOGE("%s: error getting encoding config", __func__); 1879 return ret; 1880 } 1881 CDBG_HIGH("[KPI Perf] %s : call jpeg create_session", __func__); 1882 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId); 1883 if (ret != NO_ERROR) { 1884 ALOGE("%s: error creating a new jpeg encoding session", __func__); 1885 return ret; 1886 } 1887 needNewSess = FALSE; 1888 } 1889 // Fill in new job 1890 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t)); 1891 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE; 1892 jpg_job.encode_job.session_id = mJpegSessionId; 1893 jpg_job.encode_job.src_index = (int32_t)main_frame->buf_idx; 1894 jpg_job.encode_job.dst_index = 0; 1895 1896 if (mJpegMemOpt) { 1897 jpg_job.encode_job.dst_index = jpg_job.encode_job.src_index; 1898 } else if (mUseJpegBurst) { 1899 jpg_job.encode_job.dst_index = -1; 1900 } 1901 1902 cam_dimension_t src_dim; 1903 memset(&src_dim, 0, sizeof(cam_dimension_t)); 1904 main_stream->getFrameDimension(src_dim); 1905 1906 bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled(); 1907 bool img_feature_enabled = 1908 m_parent->mParameters.isUbiFocusEnabled() || 1909 m_parent->mParameters.isUbiRefocus() || 1910 m_parent->mParameters.isChromaFlashEnabled() || 1911 m_parent->mParameters.isOptiZoomEnabled() || 1912 m_parent->mParameters.isStillMoreEnabled(); 1913 1914 CDBG_HIGH("%s:%d] Crop needed %d", __func__, __LINE__, img_feature_enabled); 1915 crop.left = 0; 1916 crop.top = 0; 1917 crop.height = src_dim.height; 1918 crop.width = src_dim.width; 1919 1920 param = main_stream->getOutputCrop(); 1921 for (int i = 0; i < param.outputCrop.num_of_streams; i++) { 1922 if (param.outputCrop.crop_info[i].stream_id 1923 == main_stream->getMyServerID()) { 1924 crop = param.outputCrop.crop_info[i].crop; 1925 main_stream->setCropInfo(crop); 1926 } 1927 } 1928 if (img_feature_enabled) { 1929 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 1930 1931 param = main_stream->getImgProp(); 1932 imgProp = param.imgProp; 1933 main_stream->setCropInfo(imgProp.crop); 1934 crop = imgProp.crop; 1935 thumb_stream = NULL; /* use thumbnail from main image */ 1936 1937 if ((reproc_stream != NULL) && (m_DataMem == NULL) && 1938 m_parent->mParameters.isUbiRefocus()) { 1939 1940 QCameraHeapMemory* miscBufHandler = reproc_stream->getMiscBuf(); 1941 cam_misc_buf_t* refocusResult = 1942 reinterpret_cast<cam_misc_buf_t *>(miscBufHandler->getPtr(0)); 1943 uint32_t resultSize = refocusResult->header_size + 1944 refocusResult->width * refocusResult->height; 1945 camera_memory_t *dataMem = m_parent->mGetMemory(-1, resultSize, 1946 1, m_parent->mCallbackCookie); 1947 1948 CDBG_HIGH("%s:%d] Refocus result header %u dims %dx%d", __func__, __LINE__, 1949 resultSize, refocusResult->width, refocusResult->height); 1950 1951 if (dataMem && dataMem->data) { 1952 memcpy(dataMem->data, refocusResult->data, resultSize); 1953 //save mem pointer for depth map 1954 m_DataMem = dataMem; 1955 } 1956 } 1957 } else if ((reproc_stream != NULL) && (m_parent->mParameters.isTruePortraitEnabled())) { 1958 1959 QCameraHeapMemory* miscBufHandler = reproc_stream->getMiscBuf(); 1960 cam_misc_buf_t* tpResult = 1961 reinterpret_cast<cam_misc_buf_t *>(miscBufHandler->getPtr(0)); 1962 uint32_t tpMetaSize = tpResult->header_size + tpResult->width * tpResult->height; 1963 1964 CDBG_HIGH("%s:%d] True portrait result header %d% dims dx%d", __func__, __LINE__, 1965 tpMetaSize, tpResult->width, tpResult->height); 1966 1967 CAM_DUMP_TO_FILE(QCAMERA_DUMP_FRM_LOCATION"tp", "bm", -1, "y", 1968 &tpResult->data, tpMetaSize); 1969 } 1970 1971 cam_dimension_t dst_dim; 1972 1973 if (hdr_output_crop && crop.height) { 1974 dst_dim.height = crop.height; 1975 } else { 1976 dst_dim.height = src_dim.height; 1977 } 1978 if (hdr_output_crop && crop.width) { 1979 dst_dim.width = crop.width; 1980 } else { 1981 dst_dim.width = src_dim.width; 1982 } 1983 1984 // main dim 1985 jpg_job.encode_job.main_dim.src_dim = src_dim; 1986 jpg_job.encode_job.main_dim.dst_dim = dst_dim; 1987 jpg_job.encode_job.main_dim.crop = crop; 1988 1989 // get 3a sw version info 1990 cam_q3a_version_t sw_version = 1991 m_parent->getCamHalCapabilities()->q3a_version; 1992 1993 // get exif data 1994 QCameraExif *pJpegExifObj = m_parent->getExifData(); 1995 jpeg_job_data->pJpegExifObj = pJpegExifObj; 1996 if (pJpegExifObj != NULL) { 1997 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries(); 1998 jpg_job.encode_job.exif_info.numOfEntries = 1999 pJpegExifObj->getNumOfEntries(); 2000 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] = 2001 sw_version.major_version; 2002 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] = 2003 sw_version.minor_version; 2004 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] = 2005 sw_version.patch_version; 2006 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] = 2007 sw_version.new_feature_des; 2008 } 2009 2010 // set rotation only when no online rotation or offline pp rotation is done before 2011 if (!m_parent->needRotationReprocess()) { 2012 jpg_job.encode_job.rotation = jpeg_rotation; 2013 } 2014 CDBG_HIGH("%s: jpeg rotation is set to %d", __func__, jpg_job.encode_job.rotation); 2015 2016 // thumbnail dim 2017 if (m_bThumbnailNeeded == TRUE) { 2018 m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim); 2019 2020 if (thumb_stream == NULL) { 2021 // need jpeg thumbnail, but no postview/preview stream exists 2022 // we use the main stream/frame to encode thumbnail 2023 thumb_stream = main_stream; 2024 thumb_frame = main_frame; 2025 if (m_parent->needRotationReprocess() && 2026 ((90 == jpeg_rotation) || (270 == jpeg_rotation))) { 2027 // swap thumbnail dimensions 2028 cam_dimension_t tmp_dim = jpg_job.encode_job.thumb_dim.dst_dim; 2029 jpg_job.encode_job.thumb_dim.dst_dim.width = tmp_dim.height; 2030 jpg_job.encode_job.thumb_dim.dst_dim.height = tmp_dim.width; 2031 } 2032 } 2033 2034 memset(&src_dim, 0, sizeof(cam_dimension_t)); 2035 thumb_stream->getFrameDimension(src_dim); 2036 jpg_job.encode_job.thumb_dim.src_dim = src_dim; 2037 2038 // crop is the same if frame is the same 2039 if (thumb_frame != main_frame) { 2040 crop.left = 0; 2041 crop.top = 0; 2042 crop.height = src_dim.height; 2043 crop.width = src_dim.width; 2044 2045 param = thumb_stream->getOutputCrop(); 2046 for (int i = 0; i < param.outputCrop.num_of_streams; i++) { 2047 if (param.outputCrop.crop_info[i].stream_id 2048 == thumb_stream->getMyServerID()) { 2049 crop = param.outputCrop.crop_info[i].crop; 2050 thumb_stream->setCropInfo(crop); 2051 } 2052 } 2053 } 2054 2055 2056 jpg_job.encode_job.thumb_dim.crop = crop; 2057 if (thumb_frame != NULL) { 2058 jpg_job.encode_job.thumb_index = thumb_frame->buf_idx; 2059 } 2060 CDBG_HIGH("%s, thumbnail src w/h (%dx%d), dst w/h (%dx%d)", __func__, 2061 jpg_job.encode_job.thumb_dim.src_dim.width, 2062 jpg_job.encode_job.thumb_dim.src_dim.height, 2063 jpg_job.encode_job.thumb_dim.dst_dim.width, 2064 jpg_job.encode_job.thumb_dim.dst_dim.height); 2065 } 2066 2067 if (thumb_frame != NULL) { 2068 // dump thumbnail frame if enabled 2069 m_parent->dumpFrameToFile(thumb_stream, thumb_frame, QCAMERA_DUMP_FRM_THUMBNAIL); 2070 } 2071 2072 if (jpeg_job_data->metadata != NULL) { 2073 // fill in meta data frame ptr 2074 jpg_job.encode_job.p_metadata = jpeg_job_data->metadata; 2075 } 2076 2077 jpg_job.encode_job.hal_version = CAM_HAL_V1; 2078 m_parent->mExifParams.sensor_params.sens_type = m_parent->getSensorType(); 2079 jpg_job.encode_job.cam_exif_params = m_parent->mExifParams; 2080 jpg_job.encode_job.mobicat_mask = m_parent->mParameters.getMobicatMask(); 2081 2082 2083 if (NULL != jpg_job.encode_job.p_metadata && (jpg_job.encode_job.mobicat_mask > 0)) { 2084 2085 /* Save a copy of mobicat params */ 2086 jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid = 2087 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid; 2088 2089 if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) { 2090 jpg_job.encode_job.p_metadata->mobicat_aec_params = 2091 jpg_job.encode_job.cam_exif_params.cam_3a_params; 2092 } 2093 2094 /* Save a copy of 3A debug params */ 2095 jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid = 2096 jpg_job.encode_job.cam_exif_params.ae_debug_params_valid; 2097 jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid = 2098 jpg_job.encode_job.cam_exif_params.awb_debug_params_valid; 2099 jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid = 2100 jpg_job.encode_job.cam_exif_params.af_debug_params_valid; 2101 jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid = 2102 jpg_job.encode_job.cam_exif_params.asd_debug_params_valid; 2103 jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid = 2104 jpg_job.encode_job.cam_exif_params.stats_debug_params_valid; 2105 2106 if (jpg_job.encode_job.cam_exif_params.ae_debug_params_valid) { 2107 jpg_job.encode_job.p_metadata->statsdebug_ae_data = 2108 jpg_job.encode_job.cam_exif_params.ae_debug_params; 2109 } 2110 if (jpg_job.encode_job.cam_exif_params.awb_debug_params_valid) { 2111 jpg_job.encode_job.p_metadata->statsdebug_awb_data = 2112 jpg_job.encode_job.cam_exif_params.awb_debug_params; 2113 } 2114 if (jpg_job.encode_job.cam_exif_params.af_debug_params_valid) { 2115 jpg_job.encode_job.p_metadata->statsdebug_af_data = 2116 jpg_job.encode_job.cam_exif_params.af_debug_params; 2117 } 2118 if (jpg_job.encode_job.cam_exif_params.asd_debug_params_valid) { 2119 jpg_job.encode_job.p_metadata->statsdebug_asd_data = 2120 jpg_job.encode_job.cam_exif_params.asd_debug_params; 2121 } 2122 if (jpg_job.encode_job.cam_exif_params.stats_debug_params_valid) { 2123 jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data = 2124 jpg_job.encode_job.cam_exif_params.stats_debug_params; 2125 } 2126 } 2127 2128 /* Init the QTable */ 2129 for (int i = 0; i < QTABLE_MAX; i++) { 2130 jpg_job.encode_job.qtable_set[i] = 0; 2131 } 2132 2133 CDBG_HIGH("[KPI Perf] %s : PROFILE_JPEG_JOB_START", __func__); 2134 ret = mJpegHandle.start_job(&jpg_job, &jobId); 2135 if (ret == NO_ERROR) { 2136 // remember job info 2137 jpeg_job_data->jobId = jobId; 2138 } 2139 2140 return ret; 2141 } 2142 2143 /*=========================================================================== 2144 * FUNCTION : processRawImageImpl 2145 * 2146 * DESCRIPTION: function to send raw image to upper layer 2147 * 2148 * PARAMETERS : 2149 * @recvd_frame : frame to be encoded 2150 * 2151 * RETURN : int32_t type of status 2152 * NO_ERROR -- success 2153 * none-zero failure code 2154 *==========================================================================*/ 2155 int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_frame) 2156 { 2157 int32_t rc = NO_ERROR; 2158 2159 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id); 2160 QCameraStream *pStream = NULL; 2161 mm_camera_buf_def_t *frame = NULL; 2162 // check reprocess channel if not found 2163 if (pChannel == NULL) { 2164 for (int8_t i = 0; i < mTotalNumReproc; i++) { 2165 if ((mPPChannels[i] != NULL) && 2166 (mPPChannels[i]->getMyHandle() == recvd_frame->ch_id)) { 2167 pChannel = mPPChannels[i]; 2168 break; 2169 } 2170 } 2171 } 2172 if (pChannel == NULL) { 2173 ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here", 2174 __func__, __LINE__, recvd_frame->ch_id); 2175 return BAD_VALUE; 2176 } 2177 2178 // find snapshot frame 2179 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) { 2180 QCameraStream *pCurStream = 2181 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id); 2182 if (pCurStream != NULL) { 2183 if (pCurStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 2184 pCurStream->isTypeOf(CAM_STREAM_TYPE_RAW) || 2185 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 2186 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)) { 2187 pStream = pCurStream; 2188 frame = recvd_frame->bufs[i]; 2189 break; 2190 } 2191 } 2192 } 2193 2194 if ( NULL == frame ) { 2195 ALOGE("%s: No valid raw buffer", __func__); 2196 return BAD_VALUE; 2197 } 2198 2199 QCameraMemory *rawMemObj = (QCameraMemory *)frame->mem_info; 2200 bool zslChannelUsed = m_parent->isZSLMode() && 2201 ( pChannel != mPPChannels[0] ); 2202 camera_memory_t *raw_mem = NULL; 2203 2204 if (rawMemObj != NULL) { 2205 if (zslChannelUsed) { 2206 raw_mem = rawMemObj->getMemory(frame->buf_idx, false); 2207 } else { 2208 raw_mem = m_parent->mGetMemory(-1, 2209 frame->frame_len, 2210 1, 2211 m_parent->mCallbackCookie); 2212 if (NULL == raw_mem) { 2213 ALOGE("%s : Not enough memory for RAW cb ", __func__); 2214 return NO_MEMORY; 2215 } 2216 memcpy(raw_mem->data, frame->buffer, frame->frame_len); 2217 } 2218 } 2219 2220 if (NULL != rawMemObj && NULL != raw_mem) { 2221 // dump frame into file 2222 if (frame->stream_type == CAM_STREAM_TYPE_SNAPSHOT || 2223 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { 2224 // for YUV422 NV16 case 2225 m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_SNAPSHOT); 2226 } else { 2227 //Received RAW snapshot taken notification 2228 m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_RAW); 2229 2230 if(true == m_parent->m_bIntRawEvtPending) { 2231 //Sending RAW snapshot taken notification to HAL 2232 memset(&m_dst_dim, 0, sizeof(m_dst_dim)); 2233 pStream->getFrameDimension(m_dst_dim); 2234 pthread_mutex_lock(&m_parent->m_int_lock); 2235 pthread_cond_signal(&m_parent->m_int_cond); 2236 pthread_mutex_unlock(&m_parent->m_int_lock); 2237 raw_mem->release(raw_mem); 2238 return rc; 2239 } 2240 } 2241 2242 // send data callback / notify for RAW_IMAGE 2243 if (NULL != m_parent->mDataCb && 2244 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) { 2245 qcamera_callback_argm_t cbArg; 2246 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 2247 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 2248 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE; 2249 cbArg.data = raw_mem; 2250 cbArg.index = 0; 2251 m_parent->m_cbNotifier.notifyCallback(cbArg); 2252 } 2253 if (NULL != m_parent->mNotifyCb && 2254 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) { 2255 qcamera_callback_argm_t cbArg; 2256 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 2257 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; 2258 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY; 2259 cbArg.ext1 = 0; 2260 cbArg.ext2 = 0; 2261 m_parent->m_cbNotifier.notifyCallback(cbArg); 2262 } 2263 2264 if ((m_parent->mDataCb != NULL) && 2265 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) > 0) { 2266 qcamera_release_data_t release_data; 2267 memset(&release_data, 0, sizeof(qcamera_release_data_t)); 2268 if ( zslChannelUsed ) { 2269 release_data.frame = recvd_frame; 2270 } else { 2271 release_data.data = raw_mem; 2272 } 2273 rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 2274 raw_mem, 2275 0, 2276 NULL, 2277 &release_data); 2278 } else { 2279 raw_mem->release(raw_mem); 2280 } 2281 } else { 2282 ALOGE("%s: Cannot get raw mem", __func__); 2283 rc = UNKNOWN_ERROR; 2284 } 2285 2286 return rc; 2287 } 2288 2289 /*=========================================================================== 2290 * FUNCTION : dataSaveRoutine 2291 * 2292 * DESCRIPTION: data saving routine 2293 * 2294 * PARAMETERS : 2295 * @data : user data ptr (QCameraPostProcessor) 2296 * 2297 * RETURN : None 2298 *==========================================================================*/ 2299 void *QCameraPostProcessor::dataSaveRoutine(void *data) 2300 { 2301 int running = 1; 2302 int ret; 2303 uint8_t is_active = FALSE; 2304 QCameraPostProcessor *pme = (QCameraPostProcessor *)data; 2305 QCameraCmdThread *cmdThread = &pme->m_saveProcTh; 2306 cmdThread->setName("CAM_JpegSave"); 2307 char saveName[PROPERTY_VALUE_MAX]; 2308 2309 CDBG_HIGH("%s: E", __func__); 2310 do { 2311 do { 2312 ret = cam_sem_wait(&cmdThread->cmd_sem); 2313 if (ret != 0 && errno != EINVAL) { 2314 ALOGE("%s: cam_sem_wait error (%s)", 2315 __func__, strerror(errno)); 2316 return NULL; 2317 } 2318 } while (ret != 0); 2319 2320 // we got notified about new cmd avail in cmd queue 2321 camera_cmd_type_t cmd = cmdThread->getCmd(); 2322 switch (cmd) { 2323 case CAMERA_CMD_TYPE_START_DATA_PROC: 2324 CDBG_HIGH("%s: start data proc", __func__); 2325 is_active = TRUE; 2326 pme->m_inputSaveQ.init(); 2327 break; 2328 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 2329 { 2330 CDBG_HIGH("%s: stop data proc", __func__); 2331 is_active = FALSE; 2332 2333 // flush input save Queue 2334 pme->m_inputSaveQ.flush(); 2335 2336 // signal cmd is completed 2337 cam_sem_post(&cmdThread->sync_sem); 2338 } 2339 break; 2340 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 2341 { 2342 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active); 2343 2344 qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) pme->m_inputSaveQ.dequeue(); 2345 if (job_data == NULL) { 2346 ALOGE("%s: Invalid jpeg event data", __func__); 2347 continue; 2348 } 2349 2350 pme->m_ongoingJpegQ.flushNodes(matchJobId, (void*)&job_data->jobId); 2351 2352 CDBG_HIGH("[KPI Perf] %s : jpeg job %d", __func__, job_data->jobId); 2353 2354 if (is_active == TRUE) { 2355 memset(saveName, '\0', sizeof(saveName)); 2356 snprintf(saveName, 2357 sizeof(saveName), 2358 QCameraPostProcessor::STORE_LOCATION, 2359 pme->mSaveFrmCnt); 2360 2361 int file_fd = open(saveName, O_RDWR | O_CREAT, 0655); 2362 if (file_fd >= 0) { 2363 ssize_t written_len = write(file_fd, job_data->out_data.buf_vaddr, 2364 job_data->out_data.buf_filled_len); 2365 if ((ssize_t)job_data->out_data.buf_filled_len != written_len) { 2366 ALOGE("%s: Failed save complete data %d bytes " 2367 "written instead of %d bytes!", 2368 __func__, written_len, 2369 job_data->out_data.buf_filled_len); 2370 } else { 2371 CDBG_HIGH("%s: written number of bytes %d\n", 2372 __func__, written_len); 2373 } 2374 2375 close(file_fd); 2376 } else { 2377 ALOGE("%s: fail t open file for saving", __func__); 2378 } 2379 pme->mSaveFrmCnt++; 2380 2381 camera_memory_t* jpeg_mem = pme->m_parent->mGetMemory(-1, 2382 strlen(saveName), 2383 1, 2384 pme->m_parent->mCallbackCookie); 2385 if (NULL == jpeg_mem) { 2386 ret = NO_MEMORY; 2387 ALOGE("%s : getMemory for jpeg, ret = NO_MEMORY", __func__); 2388 goto end; 2389 } 2390 memcpy(jpeg_mem->data, saveName, strlen(saveName)); 2391 2392 CDBG_HIGH("%s : Calling upperlayer callback to store JPEG image", __func__); 2393 qcamera_release_data_t release_data; 2394 memset(&release_data, 0, sizeof(qcamera_release_data_t)); 2395 release_data.data = jpeg_mem; 2396 release_data.unlinkFile = true; 2397 CDBG_HIGH("[KPI Perf] %s: PROFILE_JPEG_CB ",__func__); 2398 ret = pme->sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 2399 jpeg_mem, 2400 0, 2401 NULL, 2402 &release_data); 2403 } 2404 2405 end: 2406 free(job_data); 2407 } 2408 break; 2409 case CAMERA_CMD_TYPE_EXIT: 2410 CDBG_HIGH("%s : save thread exit", __func__); 2411 running = 0; 2412 break; 2413 default: 2414 break; 2415 } 2416 } while (running); 2417 CDBG_HIGH("%s: X", __func__); 2418 return NULL; 2419 } 2420 2421 /*=========================================================================== 2422 * FUNCTION : dataProcessRoutine 2423 * 2424 * DESCRIPTION: data process routine that handles input data either from input 2425 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do 2426 * reprocess. 2427 * 2428 * PARAMETERS : 2429 * @data : user data ptr (QCameraPostProcessor) 2430 * 2431 * RETURN : None 2432 *==========================================================================*/ 2433 void *QCameraPostProcessor::dataProcessRoutine(void *data) 2434 { 2435 int running = 1; 2436 int ret; 2437 uint8_t is_active = FALSE; 2438 QCameraPostProcessor *pme = (QCameraPostProcessor *)data; 2439 QCameraCmdThread *cmdThread = &pme->m_dataProcTh; 2440 cmdThread->setName("CAM_JpegProc"); 2441 2442 CDBG_HIGH("%s: E", __func__); 2443 do { 2444 do { 2445 ret = cam_sem_wait(&cmdThread->cmd_sem); 2446 if (ret != 0 && errno != EINVAL) { 2447 ALOGE("%s: cam_sem_wait error (%s)", 2448 __func__, strerror(errno)); 2449 return NULL; 2450 } 2451 } while (ret != 0); 2452 2453 // we got notified about new cmd avail in cmd queue 2454 camera_cmd_type_t cmd = cmdThread->getCmd(); 2455 switch (cmd) { 2456 case CAMERA_CMD_TYPE_START_DATA_PROC: 2457 CDBG_HIGH("%s: start data proc", __func__); 2458 is_active = TRUE; 2459 2460 pme->m_ongoingPPQ.init(); 2461 pme->m_inputJpegQ.init(); 2462 pme->m_inputPPQ.init(); 2463 pme->m_inputRawQ.init(); 2464 2465 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, 2466 FALSE, 2467 FALSE); 2468 2469 // signal cmd is completed 2470 cam_sem_post(&cmdThread->sync_sem); 2471 2472 break; 2473 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 2474 { 2475 CDBG_HIGH("%s: stop data proc", __func__); 2476 is_active = FALSE; 2477 2478 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, 2479 TRUE, 2480 TRUE); 2481 // cancel all ongoing jpeg jobs 2482 qcamera_jpeg_data_t *jpeg_job = 2483 (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 2484 while (jpeg_job != NULL) { 2485 pme->mJpegHandle.abort_job(jpeg_job->jobId); 2486 2487 pme->releaseJpegJobData(jpeg_job); 2488 free(jpeg_job); 2489 2490 jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 2491 } 2492 2493 // destroy jpeg encoding session 2494 if ( 0 < pme->mJpegSessionId ) { 2495 pme->mJpegHandle.destroy_session(pme->mJpegSessionId); 2496 pme->mJpegSessionId = 0; 2497 } 2498 2499 // free jpeg out buf and exif obj 2500 FREE_JPEG_OUTPUT_BUFFER(pme->m_pJpegOutputMem, 2501 pme->m_JpegOutputMemCount); 2502 2503 if (pme->m_pJpegExifObj != NULL) { 2504 delete pme->m_pJpegExifObj; 2505 pme->m_pJpegExifObj = NULL; 2506 } 2507 2508 // flush ongoing postproc Queue 2509 pme->m_ongoingPPQ.flush(); 2510 2511 // flush input jpeg Queue 2512 pme->m_inputJpegQ.flush(); 2513 2514 // flush input Postproc Queue 2515 pme->m_inputPPQ.flush(); 2516 2517 // flush input raw Queue 2518 pme->m_inputRawQ.flush(); 2519 2520 // signal cmd is completed 2521 cam_sem_post(&cmdThread->sync_sem); 2522 2523 pme->mNewJpegSessionNeeded = true; 2524 } 2525 break; 2526 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 2527 { 2528 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active); 2529 if (is_active == TRUE) { 2530 qcamera_jpeg_data_t *jpeg_job = 2531 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 2532 2533 if (NULL != jpeg_job) { 2534 // To avoid any race conditions, 2535 // sync any stream specific parameters here. 2536 pme->syncStreamParams(jpeg_job->src_frame, NULL); 2537 2538 // add into ongoing jpeg job Q 2539 if (pme->m_ongoingJpegQ.enqueue((void *)jpeg_job)) { 2540 ret = pme->encodeData(jpeg_job, 2541 pme->mNewJpegSessionNeeded); 2542 if (NO_ERROR != ret) { 2543 // dequeue the last one 2544 pme->m_ongoingJpegQ.dequeue(false); 2545 pme->releaseJpegJobData(jpeg_job); 2546 free(jpeg_job); 2547 jpeg_job = NULL; 2548 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 2549 } 2550 } else { 2551 CDBG_HIGH("%s : m_ongoingJpegQ is not active!!!", __func__); 2552 pme->releaseJpegJobData(jpeg_job); 2553 free(jpeg_job); 2554 jpeg_job = NULL; 2555 } 2556 } 2557 2558 2559 // process raw data if any 2560 mm_camera_super_buf_t *super_buf = 2561 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 2562 2563 if (NULL != super_buf) { 2564 //play shutter sound 2565 pme->m_parent->playShutter(); 2566 ret = pme->processRawImageImpl(super_buf); 2567 if (NO_ERROR != ret) { 2568 pme->releaseSuperBuf(super_buf); 2569 free(super_buf); 2570 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 2571 } 2572 } 2573 2574 ret = pme->doReprocess(); 2575 if (NO_ERROR != ret) { 2576 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 2577 } else { 2578 ret = pme->stopCapture(); 2579 } 2580 2581 } else { 2582 // not active, simply return buf and do no op 2583 qcamera_jpeg_data_t *jpeg_data = 2584 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 2585 if (NULL != jpeg_data) { 2586 pme->releaseJpegJobData(jpeg_data); 2587 free(jpeg_data); 2588 } 2589 mm_camera_super_buf_t *super_buf = 2590 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 2591 if (NULL != super_buf) { 2592 pme->releaseSuperBuf(super_buf); 2593 free(super_buf); 2594 } 2595 2596 // flush input Postproc Queue 2597 pme->m_inputPPQ.flush(); 2598 } 2599 } 2600 break; 2601 case CAMERA_CMD_TYPE_EXIT: 2602 running = 0; 2603 break; 2604 default: 2605 break; 2606 } 2607 } while (running); 2608 CDBG_HIGH("%s: X", __func__); 2609 return NULL; 2610 } 2611 2612 /*=========================================================================== 2613 * FUNCTION : doReprocess 2614 * 2615 * DESCRIPTION: Trigger channel reprocessing 2616 * 2617 * PARAMETERS :None 2618 * 2619 * RETURN : int32_t type of status 2620 * NO_ERROR -- success 2621 * none-zero failure code 2622 *==========================================================================*/ 2623 int32_t QCameraPostProcessor::doReprocess() 2624 { 2625 int32_t ret = NO_ERROR; 2626 QCameraChannel *m_pSrcChannel; 2627 QCameraStream *pMetaStream = NULL; 2628 uint8_t meta_buf_index = 0; 2629 mm_camera_buf_def_t *meta_buf = NULL; 2630 bool found_meta = FALSE; 2631 2632 qcamera_pp_request_t *ppreq_job = (qcamera_pp_request_t *)m_inputPPQ.peek(); 2633 if ((ppreq_job == NULL) || (ppreq_job->src_frame == NULL)) { 2634 return ret; 2635 } 2636 2637 if (!validatePostProcess(ppreq_job->src_frame)) { 2638 return ret; 2639 } 2640 2641 ppreq_job = (qcamera_pp_request_t *)m_inputPPQ.dequeue(); 2642 if (ppreq_job == NULL || ppreq_job->src_frame == NULL || 2643 ppreq_job->src_reproc_frame == NULL) { 2644 return ret; 2645 } 2646 2647 mm_camera_super_buf_t *src_frame = ppreq_job->src_frame; 2648 mm_camera_super_buf_t *src_reproc_frame = ppreq_job->src_reproc_frame; 2649 int8_t mCurReprocCount = ppreq_job->reprocCount; 2650 2651 CDBG("%s: frame = %p src_frame = %p mCurReprocCount = %d",__func__, 2652 src_frame,src_reproc_frame,mCurReprocCount); 2653 2654 // find meta data stream and index of meta data frame in the superbuf 2655 for (int8_t j = 0; j < mTotalNumReproc; j++) { 2656 uint32_t i; 2657 m_pSrcChannel = mPPChannels[j]->getSrcChannel(); 2658 if (m_pSrcChannel == NULL) 2659 continue; 2660 for (i = 0; i < src_reproc_frame->num_bufs; i++) { 2661 QCameraStream *pStream = 2662 m_pSrcChannel->getStreamByHandle(src_reproc_frame->bufs[i]->stream_id); 2663 if (pStream != NULL && pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) { 2664 meta_buf_index = (uint8_t) src_reproc_frame->bufs[i]->buf_idx; 2665 pMetaStream = pStream; 2666 meta_buf = src_reproc_frame->bufs[i]; 2667 break; 2668 } 2669 } 2670 if (i < src_reproc_frame->num_bufs) { 2671 CDBG(" %s: Found Meta data info for reprocessing index = %d", __func__, 2672 (int)meta_buf_index); 2673 break; 2674 } 2675 } 2676 2677 qcamera_pp_data_t *pp_job = 2678 (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t)); 2679 if (pp_job != NULL) { 2680 syncStreamParams(src_frame, src_reproc_frame); 2681 memset(pp_job, 0, sizeof(qcamera_pp_data_t)); 2682 if (mPPChannels[mCurReprocCount] != NULL) { 2683 // add into ongoing PP job Q 2684 pp_job->src_frame = src_frame; 2685 pp_job->src_reproc_frame = src_reproc_frame; 2686 pp_job->reprocCount = (int8_t) (mCurReprocCount + 1); 2687 2688 if (m_parent->isRegularCapture()) { 2689 if ((NULL != pp_job->src_frame) && 2690 (0 < pp_job->src_frame->num_bufs)) { 2691 mm_camera_buf_def_t *bufs = NULL; 2692 uint32_t num_bufs = pp_job->src_frame->num_bufs; 2693 bufs = new mm_camera_buf_def_t[num_bufs]; 2694 if (NULL == bufs) { 2695 ALOGE("%s:Unable to allocate cached buffers", 2696 __func__); 2697 return NO_MEMORY; 2698 } 2699 2700 for (uint32_t i = 0; i < num_bufs; i++) { 2701 bufs[i] = *pp_job->src_frame->bufs[i]; 2702 pp_job->src_frame->bufs[i] = &bufs[i]; 2703 } 2704 pp_job->src_reproc_bufs = bufs; 2705 } 2706 2707 m_bufCountPPQ++; 2708 2709 // Don't release source frame after encoding 2710 // at this point the source channel will not exist. 2711 pp_job->reproc_frame_release = true; 2712 if (m_ongoingPPQ.enqueue((void *)pp_job)) { 2713 ret = mPPChannels[mCurReprocCount]->doReprocessOffline(pp_job->src_frame, 2714 meta_buf); 2715 } else { 2716 CDBG_HIGH("%s : m_ongoingJpegQ is not active!!!", __func__); 2717 releaseOngoingPPData(pp_job, this); 2718 free(pp_job); 2719 pp_job = NULL; 2720 } 2721 } else { 2722 2723 m_bufCountPPQ++; 2724 if (!m_ongoingPPQ.enqueue((void *)pp_job)) { 2725 CDBG_HIGH("%s : m_ongoingJpegQ is not active!!!", __func__); 2726 releaseOngoingPPData(pp_job, this); 2727 free(pp_job); 2728 pp_job = NULL; 2729 goto end; 2730 } 2731 2732 int32_t numRequiredPPQBufsForSingleOutput = (int32_t) 2733 m_parent->mParameters.getNumberInBufsForSingleShot(); 2734 2735 if (m_bufCountPPQ % numRequiredPPQBufsForSingleOutput == 0) { 2736 int32_t extra_pp_job_count = 2737 m_parent->mParameters.getNumberOutBufsForSingleShot() - 2738 m_parent->mParameters.getNumberInBufsForSingleShot(); 2739 2740 for (int32_t i = 0; i < extra_pp_job_count; i++) { 2741 qcamera_pp_data_t *extra_pp_job = 2742 (qcamera_pp_data_t *)calloc(1, sizeof(qcamera_pp_data_t)); 2743 if (!extra_pp_job) { 2744 ALOGE("%s: no mem for qcamera_pp_data_t", __func__); 2745 ret = NO_MEMORY; 2746 break; 2747 } 2748 extra_pp_job->reprocCount = pp_job->reprocCount; 2749 if (!m_ongoingPPQ.enqueue((void *)extra_pp_job)) { 2750 CDBG_HIGH("%s : m_ongoingJpegQ is not active!!!", __func__); 2751 releaseOngoingPPData(extra_pp_job, this); 2752 free(extra_pp_job); 2753 extra_pp_job = NULL; 2754 goto end; 2755 } 2756 } 2757 } 2758 2759 ret = mPPChannels[mCurReprocCount]->doReprocess(pp_job->src_frame, 2760 m_parent->mParameters, pMetaStream, meta_buf_index); 2761 } 2762 } else { 2763 ALOGE("%s: Reprocess channel is NULL", __func__); 2764 if (pp_job != NULL) { 2765 free(pp_job); 2766 pp_job = NULL; 2767 } 2768 releasePPInputData(ppreq_job, this); 2769 ret = UNKNOWN_ERROR; 2770 } 2771 } else { 2772 ALOGE("%s: no mem for qcamera_pp_data_t", __func__); 2773 ret = NO_MEMORY; 2774 } 2775 2776 end: 2777 free(ppreq_job); 2778 ppreq_job = NULL; 2779 return ret; 2780 } 2781 2782 /*=========================================================================== 2783 * FUNCTION : getReprocChannel 2784 * 2785 * DESCRIPTION: Returns reprocessing channel handle 2786 * 2787 * PARAMETERS : index for reprocessing array 2788 * 2789 * RETURN : QCameraReprocessChannel * type of pointer 2790 NULL if no reprocessing channel 2791 *==========================================================================*/ 2792 QCameraReprocessChannel * QCameraPostProcessor::getReprocChannel(uint8_t index) 2793 { 2794 if (index >= mTotalNumReproc) { 2795 ALOGE("%s: Invalid index value",__func__); 2796 return NULL; 2797 } 2798 return mPPChannels[index]; 2799 } 2800 2801 /*=========================================================================== 2802 * FUNCTION : stopCapture 2803 * 2804 * DESCRIPTION: Trigger image capture stop 2805 * 2806 * PARAMETERS : 2807 * None 2808 * 2809 * RETURN : int32_t type of status 2810 * NO_ERROR -- success 2811 * none-zero failure code 2812 *==========================================================================*/ 2813 int32_t QCameraPostProcessor::stopCapture() 2814 { 2815 int rc = NO_ERROR; 2816 2817 if (m_parent->isRegularCapture()) { 2818 rc = m_parent->processAPI( 2819 QCAMERA_SM_EVT_STOP_CAPTURE_CHANNEL, 2820 NULL); 2821 } 2822 2823 return rc; 2824 } 2825 2826 /*=========================================================================== 2827 * FUNCTION : getJpegPaddingReq 2828 * 2829 * DESCRIPTION: function to add an entry to exif data 2830 * 2831 * PARAMETERS : 2832 * @padding_info : jpeg specific padding requirement 2833 * 2834 * RETURN : int32_t type of status 2835 * NO_ERROR -- success 2836 * none-zero failure code 2837 *==========================================================================*/ 2838 int32_t QCameraPostProcessor::getJpegPaddingReq(cam_padding_info_t &padding_info) 2839 { 2840 // TODO: hardcode for now, needs to query from mm-jpeg-interface 2841 padding_info.width_padding = CAM_PAD_NONE; 2842 padding_info.height_padding = CAM_PAD_TO_16; 2843 padding_info.plane_padding = CAM_PAD_TO_WORD; 2844 return NO_ERROR; 2845 } 2846 2847 /*=========================================================================== 2848 * FUNCTION : setYUVFrameInfo 2849 * 2850 * DESCRIPTION: set Raw YUV frame data info for up-layer 2851 * 2852 * PARAMETERS : 2853 * @frame : process frame received from mm-camera-interface 2854 * 2855 * RETURN : int32_t type of status 2856 * NO_ERROR -- success 2857 * none-zero failure code 2858 * 2859 * NOTE : currently we return frame len, y offset, cbcr offset and frame format 2860 *==========================================================================*/ 2861 int32_t QCameraPostProcessor::setYUVFrameInfo(mm_camera_super_buf_t *recvd_frame) 2862 { 2863 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id); 2864 // check reprocess channel if not found 2865 if (pChannel == NULL) { 2866 for (int8_t i = 0; i < mTotalNumReproc; i++) { 2867 if ((mPPChannels[i] != NULL) && 2868 (mPPChannels[i]->getMyHandle() == recvd_frame->ch_id)) { 2869 pChannel = mPPChannels[i]; 2870 break; 2871 } 2872 } 2873 } 2874 2875 if (pChannel == NULL) { 2876 ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here", 2877 __func__, __LINE__, recvd_frame->ch_id); 2878 return BAD_VALUE; 2879 } 2880 2881 // find snapshot frame 2882 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) { 2883 QCameraStream *pStream = 2884 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id); 2885 if (pStream != NULL) { 2886 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 2887 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { 2888 //get the main frame, use stream info 2889 cam_frame_len_offset_t frame_offset; 2890 cam_dimension_t frame_dim; 2891 cam_format_t frame_fmt; 2892 const char *fmt_string; 2893 pStream->getFrameDimension(frame_dim); 2894 pStream->getFrameOffset(frame_offset); 2895 pStream->getFormat(frame_fmt); 2896 fmt_string = m_parent->mParameters.getFrameFmtString(frame_fmt); 2897 2898 int cbcr_offset = (int32_t)frame_offset.mp[0].len - 2899 frame_dim.width * frame_dim.height; 2900 m_parent->mParameters.set("snapshot-framelen", (int)frame_offset.frame_len); 2901 m_parent->mParameters.set("snapshot-yoff", (int)frame_offset.mp[0].offset); 2902 m_parent->mParameters.set("snapshot-cbcroff", cbcr_offset); 2903 if (fmt_string != NULL) { 2904 m_parent->mParameters.set("snapshot-format", fmt_string); 2905 } else { 2906 m_parent->mParameters.set("snapshot-format", ""); 2907 } 2908 2909 CDBG_HIGH("%s: frame width=%d, height=%d, yoff=%d, cbcroff=%d, fmt_string=%s", __func__, 2910 frame_dim.width, frame_dim.height, frame_offset.mp[0].offset, cbcr_offset, fmt_string); 2911 return NO_ERROR; 2912 } 2913 } 2914 } 2915 2916 return BAD_VALUE; 2917 } 2918 2919 bool QCameraPostProcessor::matchJobId(void *data, void *, void *match_data) 2920 { 2921 qcamera_jpeg_data_t * job = (qcamera_jpeg_data_t *) data; 2922 uint32_t job_id = *((uint32_t *) match_data); 2923 return job->jobId == job_id; 2924 } 2925 2926 /*=========================================================================== 2927 * FUNCTION : getJpegMemory 2928 * 2929 * DESCRIPTION: buffer allocation function 2930 * to pass to jpeg interface 2931 * 2932 * PARAMETERS : 2933 * @out_buf : buffer descriptor struct 2934 * 2935 * RETURN : int32_t type of status 2936 * NO_ERROR -- success 2937 * none-zero failure code 2938 *==========================================================================*/ 2939 int QCameraPostProcessor::getJpegMemory(omx_jpeg_ouput_buf_t *out_buf) 2940 { 2941 CDBG_HIGH("%s: Allocating jpeg out buffer of size: %d", __func__, out_buf->size); 2942 QCameraPostProcessor *procInst = (QCameraPostProcessor *) out_buf->handle; 2943 camera_memory_t *cam_mem = procInst->m_parent->mGetMemory(out_buf->fd, out_buf->size, 1U, 2944 procInst->m_parent->mCallbackCookie); 2945 out_buf->mem_hdl = cam_mem; 2946 out_buf->vaddr = cam_mem->data; 2947 2948 return 0; 2949 } 2950 2951 /*=========================================================================== 2952 * FUNCTION : QCameraExif 2953 * 2954 * DESCRIPTION: constructor of QCameraExif 2955 * 2956 * PARAMETERS : None 2957 * 2958 * RETURN : None 2959 *==========================================================================*/ 2960 QCameraExif::QCameraExif() 2961 : m_nNumEntries(0) 2962 { 2963 memset(m_Entries, 0, sizeof(m_Entries)); 2964 } 2965 2966 /*=========================================================================== 2967 * FUNCTION : ~QCameraExif 2968 * 2969 * DESCRIPTION: deconstructor of QCameraExif. Will release internal memory ptr. 2970 * 2971 * PARAMETERS : None 2972 * 2973 * RETURN : None 2974 *==========================================================================*/ 2975 QCameraExif::~QCameraExif() 2976 { 2977 for (uint32_t i = 0; i < m_nNumEntries; i++) { 2978 switch (m_Entries[i].tag_entry.type) { 2979 case EXIF_BYTE: 2980 { 2981 if (m_Entries[i].tag_entry.count > 1 && 2982 m_Entries[i].tag_entry.data._bytes != NULL) { 2983 free(m_Entries[i].tag_entry.data._bytes); 2984 m_Entries[i].tag_entry.data._bytes = NULL; 2985 } 2986 } 2987 break; 2988 case EXIF_ASCII: 2989 { 2990 if (m_Entries[i].tag_entry.data._ascii != NULL) { 2991 free(m_Entries[i].tag_entry.data._ascii); 2992 m_Entries[i].tag_entry.data._ascii = NULL; 2993 } 2994 } 2995 break; 2996 case EXIF_SHORT: 2997 { 2998 if (m_Entries[i].tag_entry.count > 1 && 2999 m_Entries[i].tag_entry.data._shorts != NULL) { 3000 free(m_Entries[i].tag_entry.data._shorts); 3001 m_Entries[i].tag_entry.data._shorts = NULL; 3002 } 3003 } 3004 break; 3005 case EXIF_LONG: 3006 { 3007 if (m_Entries[i].tag_entry.count > 1 && 3008 m_Entries[i].tag_entry.data._longs != NULL) { 3009 free(m_Entries[i].tag_entry.data._longs); 3010 m_Entries[i].tag_entry.data._longs = NULL; 3011 } 3012 } 3013 break; 3014 case EXIF_RATIONAL: 3015 { 3016 if (m_Entries[i].tag_entry.count > 1 && 3017 m_Entries[i].tag_entry.data._rats != NULL) { 3018 free(m_Entries[i].tag_entry.data._rats); 3019 m_Entries[i].tag_entry.data._rats = NULL; 3020 } 3021 } 3022 break; 3023 case EXIF_UNDEFINED: 3024 { 3025 if (m_Entries[i].tag_entry.data._undefined != NULL) { 3026 free(m_Entries[i].tag_entry.data._undefined); 3027 m_Entries[i].tag_entry.data._undefined = NULL; 3028 } 3029 } 3030 break; 3031 case EXIF_SLONG: 3032 { 3033 if (m_Entries[i].tag_entry.count > 1 && 3034 m_Entries[i].tag_entry.data._slongs != NULL) { 3035 free(m_Entries[i].tag_entry.data._slongs); 3036 m_Entries[i].tag_entry.data._slongs = NULL; 3037 } 3038 } 3039 break; 3040 case EXIF_SRATIONAL: 3041 { 3042 if (m_Entries[i].tag_entry.count > 1 && 3043 m_Entries[i].tag_entry.data._srats != NULL) { 3044 free(m_Entries[i].tag_entry.data._srats); 3045 m_Entries[i].tag_entry.data._srats = NULL; 3046 } 3047 } 3048 break; 3049 } 3050 } 3051 } 3052 3053 /*=========================================================================== 3054 * FUNCTION : addEntry 3055 * 3056 * DESCRIPTION: function to add an entry to exif data 3057 * 3058 * PARAMETERS : 3059 * @tagid : exif tag ID 3060 * @type : data type 3061 * @count : number of data in uint of its type 3062 * @data : input data ptr 3063 * 3064 * RETURN : int32_t type of status 3065 * NO_ERROR -- success 3066 * none-zero failure code 3067 *==========================================================================*/ 3068 int32_t QCameraExif::addEntry(exif_tag_id_t tagid, 3069 exif_tag_type_t type, 3070 uint32_t count, 3071 void *data) 3072 { 3073 int32_t rc = NO_ERROR; 3074 if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) { 3075 ALOGE("%s: Number of entries exceeded limit", __func__); 3076 return NO_MEMORY; 3077 } 3078 3079 m_Entries[m_nNumEntries].tag_id = tagid; 3080 m_Entries[m_nNumEntries].tag_entry.type = type; 3081 m_Entries[m_nNumEntries].tag_entry.count = count; 3082 m_Entries[m_nNumEntries].tag_entry.copy = 1; 3083 switch (type) { 3084 case EXIF_BYTE: 3085 { 3086 if (count > 1) { 3087 uint8_t *values = (uint8_t *)malloc(count); 3088 if (values == NULL) { 3089 ALOGE("%s: No memory for byte array", __func__); 3090 rc = NO_MEMORY; 3091 } else { 3092 memcpy(values, data, count); 3093 m_Entries[m_nNumEntries].tag_entry.data._bytes = values; 3094 } 3095 } else { 3096 m_Entries[m_nNumEntries].tag_entry.data._byte = *(uint8_t *)data; 3097 } 3098 } 3099 break; 3100 case EXIF_ASCII: 3101 { 3102 char *str = NULL; 3103 str = (char *)malloc(count + 1); 3104 if (str == NULL) { 3105 ALOGE("%s: No memory for ascii string", __func__); 3106 rc = NO_MEMORY; 3107 } else { 3108 memset(str, 0, count + 1); 3109 memcpy(str, data, count); 3110 m_Entries[m_nNumEntries].tag_entry.data._ascii = str; 3111 } 3112 } 3113 break; 3114 case EXIF_SHORT: 3115 { 3116 if (count > 1) { 3117 uint16_t *values = (uint16_t *)malloc(count * sizeof(uint16_t)); 3118 if (values == NULL) { 3119 ALOGE("%s: No memory for short array", __func__); 3120 rc = NO_MEMORY; 3121 } else { 3122 memcpy(values, data, count * sizeof(uint16_t)); 3123 m_Entries[m_nNumEntries].tag_entry.data._shorts = values; 3124 } 3125 } else { 3126 m_Entries[m_nNumEntries].tag_entry.data._short = *(uint16_t *)data; 3127 } 3128 } 3129 break; 3130 case EXIF_LONG: 3131 { 3132 if (count > 1) { 3133 uint32_t *values = (uint32_t *)malloc(count * sizeof(uint32_t)); 3134 if (values == NULL) { 3135 ALOGE("%s: No memory for long array", __func__); 3136 rc = NO_MEMORY; 3137 } else { 3138 memcpy(values, data, count * sizeof(uint32_t)); 3139 m_Entries[m_nNumEntries].tag_entry.data._longs = values; 3140 } 3141 } else { 3142 m_Entries[m_nNumEntries].tag_entry.data._long = *(uint32_t *)data; 3143 } 3144 } 3145 break; 3146 case EXIF_RATIONAL: 3147 { 3148 if (count > 1) { 3149 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t)); 3150 if (values == NULL) { 3151 ALOGE("%s: No memory for rational array", __func__); 3152 rc = NO_MEMORY; 3153 } else { 3154 memcpy(values, data, count * sizeof(rat_t)); 3155 m_Entries[m_nNumEntries].tag_entry.data._rats = values; 3156 } 3157 } else { 3158 m_Entries[m_nNumEntries].tag_entry.data._rat = *(rat_t *)data; 3159 } 3160 } 3161 break; 3162 case EXIF_UNDEFINED: 3163 { 3164 uint8_t *values = (uint8_t *)malloc(count); 3165 if (values == NULL) { 3166 ALOGE("%s: No memory for undefined array", __func__); 3167 rc = NO_MEMORY; 3168 } else { 3169 memcpy(values, data, count); 3170 m_Entries[m_nNumEntries].tag_entry.data._undefined = values; 3171 } 3172 } 3173 break; 3174 case EXIF_SLONG: 3175 { 3176 if (count > 1) { 3177 int32_t *values = (int32_t *)malloc(count * sizeof(int32_t)); 3178 if (values == NULL) { 3179 ALOGE("%s: No memory for signed long array", __func__); 3180 rc = NO_MEMORY; 3181 } else { 3182 memcpy(values, data, count * sizeof(int32_t)); 3183 m_Entries[m_nNumEntries].tag_entry.data._slongs = values; 3184 } 3185 } else { 3186 m_Entries[m_nNumEntries].tag_entry.data._slong = *(int32_t *)data; 3187 } 3188 } 3189 break; 3190 case EXIF_SRATIONAL: 3191 { 3192 if (count > 1) { 3193 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t)); 3194 if (values == NULL) { 3195 ALOGE("%s: No memory for signed rational array", __func__); 3196 rc = NO_MEMORY; 3197 } else { 3198 memcpy(values, data, count * sizeof(srat_t)); 3199 m_Entries[m_nNumEntries].tag_entry.data._srats = values; 3200 } 3201 } else { 3202 m_Entries[m_nNumEntries].tag_entry.data._srat = *(srat_t *)data; 3203 } 3204 } 3205 break; 3206 } 3207 3208 // Increase number of entries 3209 m_nNumEntries++; 3210 return rc; 3211 } 3212 3213 }; // namespace qcamera 3214