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