1 /* Copyright (c) 2012-2013, 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 <stdlib.h> 33 #include <utils/Errors.h> 34 35 #include "QCamera2HWI.h" 36 #include "QCameraPostProc.h" 37 38 namespace qcamera { 39 40 /*=========================================================================== 41 * FUNCTION : QCameraPostProcessor 42 * 43 * DESCRIPTION: constructor of QCameraPostProcessor. 44 * 45 * PARAMETERS : 46 * @cam_ctrl : ptr to HWI object 47 * 48 * RETURN : None 49 *==========================================================================*/ 50 QCameraPostProcessor::QCameraPostProcessor(QCamera2HardwareInterface *cam_ctrl) 51 : m_parent(cam_ctrl), 52 mJpegCB(NULL), 53 mJpegUserData(NULL), 54 mJpegClientHandle(0), 55 mJpegSessionId(0), 56 m_pJpegOutputMem(NULL), 57 m_pJpegExifObj(NULL), 58 m_bThumbnailNeeded(TRUE), 59 m_pReprocChannel(NULL), 60 m_inputPPQ(releasePPInputData, this), 61 m_ongoingPPQ(releaseOngoingPPData, this), 62 m_inputJpegQ(releaseJpegData, this), 63 m_ongoingJpegQ(releaseJpegData, this), 64 m_inputRawQ(releasePPInputData, this) 65 { 66 memset(&mJpegHandle, 0, sizeof(mJpegHandle)); 67 } 68 69 /*=========================================================================== 70 * FUNCTION : ~QCameraPostProcessor 71 * 72 * DESCRIPTION: deconstructor of QCameraPostProcessor. 73 * 74 * PARAMETERS : None 75 * 76 * RETURN : None 77 *==========================================================================*/ 78 QCameraPostProcessor::~QCameraPostProcessor() 79 { 80 if (m_pJpegOutputMem != NULL) { 81 m_pJpegOutputMem->deallocate(); 82 delete m_pJpegOutputMem; 83 m_pJpegOutputMem = NULL; 84 } 85 if (m_pJpegExifObj != NULL) { 86 delete m_pJpegExifObj; 87 m_pJpegExifObj = NULL; 88 } 89 if (m_pReprocChannel != NULL) { 90 m_pReprocChannel->stop(); 91 delete m_pReprocChannel; 92 m_pReprocChannel = NULL; 93 } 94 } 95 96 /*=========================================================================== 97 * FUNCTION : init 98 * 99 * DESCRIPTION: initialization of postprocessor 100 * 101 * PARAMETERS : 102 * @jpeg_cb : callback to handle jpeg event from mm-camera-interface 103 * @user_data : user data ptr for jpeg callback 104 * 105 * RETURN : int32_t type of status 106 * NO_ERROR -- success 107 * none-zero failure code 108 *==========================================================================*/ 109 int32_t QCameraPostProcessor::init(jpeg_encode_callback_t jpeg_cb, void *user_data) 110 { 111 mJpegCB = jpeg_cb; 112 mJpegUserData = user_data; 113 114 mJpegClientHandle = jpeg_open(&mJpegHandle); 115 if(!mJpegClientHandle) { 116 ALOGE("%s : jpeg_open did not work", __func__); 117 return UNKNOWN_ERROR; 118 } 119 120 m_dataProcTh.launch(dataProcessRoutine, this); 121 122 return NO_ERROR; 123 } 124 125 /*=========================================================================== 126 * FUNCTION : deinit 127 * 128 * DESCRIPTION: de-initialization of postprocessor 129 * 130 * PARAMETERS : None 131 * 132 * RETURN : int32_t type of status 133 * NO_ERROR -- success 134 * none-zero failure code 135 *==========================================================================*/ 136 int32_t QCameraPostProcessor::deinit() 137 { 138 m_dataProcTh.exit(); 139 140 if(mJpegClientHandle > 0) { 141 int rc = mJpegHandle.close(mJpegClientHandle); 142 ALOGE("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x", 143 __func__, rc, mJpegClientHandle); 144 mJpegClientHandle = 0; 145 memset(&mJpegHandle, 0, sizeof(mJpegHandle)); 146 } 147 148 return NO_ERROR; 149 } 150 151 /*=========================================================================== 152 * FUNCTION : start 153 * 154 * DESCRIPTION: start postprocessor. Data process thread and data notify thread 155 * will be launched. 156 * 157 * PARAMETERS : 158 * @pSrcChannel : source channel obj ptr that possibly needs reprocess 159 * 160 * RETURN : int32_t type of status 161 * NO_ERROR -- success 162 * none-zero failure code 163 * 164 * NOTE : if any reprocess is needed, a reprocess channel/stream 165 * will be started. 166 *==========================================================================*/ 167 int32_t QCameraPostProcessor::start(QCameraChannel *pSrcChannel) 168 { 169 int32_t rc = NO_ERROR; 170 if (m_parent->needReprocess()) { 171 if (m_pReprocChannel != NULL) { 172 delete m_pReprocChannel; 173 m_pReprocChannel = NULL; 174 } 175 // if reprocess is needed, start reprocess channel 176 m_pReprocChannel = m_parent->addOnlineReprocChannel(pSrcChannel); 177 if (m_pReprocChannel == NULL) { 178 ALOGE("%s: cannot add reprocess channel", __func__); 179 return UNKNOWN_ERROR; 180 } 181 182 rc = m_pReprocChannel->start(); 183 if (rc != 0) { 184 ALOGE("%s: cannot start reprocess channel", __func__); 185 delete m_pReprocChannel; 186 m_pReprocChannel = NULL; 187 return rc; 188 } 189 } 190 191 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE); 192 m_parent->m_cbNotifier.startSnapshots(); 193 194 return rc; 195 } 196 197 /*=========================================================================== 198 * FUNCTION : stop 199 * 200 * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped. 201 * 202 * PARAMETERS : None 203 * 204 * RETURN : int32_t type of status 205 * NO_ERROR -- success 206 * none-zero failure code 207 * 208 * NOTE : reprocess channel will be stopped and deleted if there is any 209 *==========================================================================*/ 210 int32_t QCameraPostProcessor::stop() 211 { 212 m_parent->m_cbNotifier.stopSnapshots(); 213 // dataProc Thread need to process "stop" as sync call because abort jpeg job should be a sync call 214 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE); 215 216 return NO_ERROR; 217 } 218 219 /*=========================================================================== 220 * FUNCTION : getJpegEncodingConfig 221 * 222 * DESCRIPTION: function to prepare encoding job information 223 * 224 * PARAMETERS : 225 * @encode_parm : param to be filled with encoding configuration 226 * 227 * RETURN : int32_t type of status 228 * NO_ERROR -- success 229 * none-zero failure code 230 *==========================================================================*/ 231 int32_t QCameraPostProcessor::getJpegEncodingConfig(mm_jpeg_encode_params_t& encode_parm, 232 QCameraStream *main_stream, 233 QCameraStream *thumb_stream) 234 { 235 ALOGV("%s : E", __func__); 236 int32_t ret = NO_ERROR; 237 camera_memory_t *jpeg_mem = NULL; 238 239 encode_parm.jpeg_cb = mJpegCB; 240 encode_parm.userdata = mJpegUserData; 241 242 m_bThumbnailNeeded = TRUE; // need encode thumbnail by default 243 cam_dimension_t thumbnailSize; 244 memset(&thumbnailSize, 0, sizeof(cam_dimension_t)); 245 m_parent->getThumbnailSize(thumbnailSize); 246 if (thumbnailSize.width == 0 || thumbnailSize.height == 0) { 247 // (0,0) means no thumbnail 248 m_bThumbnailNeeded = FALSE; 249 } 250 encode_parm.encode_thumbnail = m_bThumbnailNeeded; 251 252 // get color format 253 cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12; 254 main_stream->getFormat(img_fmt); 255 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt); 256 257 // get jpeg quality 258 encode_parm.quality = m_parent->getJpegQuality(); 259 if (encode_parm.quality <= 0) { 260 encode_parm.quality = 85; 261 } 262 263 // get exif data 264 if (m_pJpegExifObj != NULL) { 265 delete m_pJpegExifObj; 266 m_pJpegExifObj = NULL; 267 } 268 m_pJpegExifObj = m_parent->getExifData(); 269 if (m_pJpegExifObj != NULL) { 270 encode_parm.exif_info.exif_data = m_pJpegExifObj->getEntries(); 271 encode_parm.exif_info.numOfEntries = m_pJpegExifObj->getNumOfEntries(); 272 } 273 274 cam_frame_len_offset_t main_offset; 275 memset(&main_offset, 0, sizeof(cam_frame_len_offset_t)); 276 main_stream->getFrameOffset(main_offset); 277 278 // src buf config 279 QCameraMemory *pStreamMem = main_stream->getStreamBufs(); 280 if (pStreamMem == NULL) { 281 ALOGE("%s: cannot get stream bufs from main stream", __func__); 282 ret = BAD_VALUE; 283 goto on_error; 284 } 285 encode_parm.num_src_bufs = pStreamMem->getCnt(); 286 for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) { 287 camera_memory_t *stream_mem = pStreamMem->getMemory(i, false); 288 if (stream_mem != NULL) { 289 encode_parm.src_main_buf[i].index = i; 290 encode_parm.src_main_buf[i].buf_size = stream_mem->size; 291 encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)stream_mem->data; 292 encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i); 293 encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV; 294 encode_parm.src_main_buf[i].offset = main_offset; 295 } 296 } 297 298 if (m_bThumbnailNeeded == TRUE) { 299 if (thumb_stream == NULL) { 300 thumb_stream = main_stream; 301 } 302 pStreamMem = thumb_stream->getStreamBufs(); 303 if (pStreamMem == NULL) { 304 ALOGE("%s: cannot get stream bufs from thumb stream", __func__); 305 ret = BAD_VALUE; 306 goto on_error; 307 } 308 cam_frame_len_offset_t thumb_offset; 309 memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t)); 310 thumb_stream->getFrameOffset(thumb_offset); 311 encode_parm.num_tmb_bufs = pStreamMem->getCnt(); 312 for (int i = 0; i < pStreamMem->getCnt(); i++) { 313 camera_memory_t *stream_mem = pStreamMem->getMemory(i, false); 314 if (stream_mem != NULL) { 315 encode_parm.src_thumb_buf[i].index = i; 316 encode_parm.src_thumb_buf[i].buf_size = stream_mem->size; 317 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)stream_mem->data; 318 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i); 319 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV; 320 encode_parm.src_thumb_buf[i].offset = thumb_offset; 321 } 322 } 323 } 324 325 // allocate output buf for jpeg encoding 326 if (m_pJpegOutputMem != NULL) { 327 m_pJpegOutputMem->deallocate(); 328 delete m_pJpegOutputMem; 329 m_pJpegOutputMem = NULL; 330 } 331 m_pJpegOutputMem = new QCameraStreamMemory(m_parent->mGetMemory, 332 QCAMERA_ION_USE_CACHE); 333 if (NULL == m_pJpegOutputMem) { 334 ret = NO_MEMORY; 335 ALOGE("%s : No memory for m_pJpegOutputMem", __func__); 336 goto on_error; 337 } 338 ret = m_pJpegOutputMem->allocate(1, main_offset.frame_len); 339 if(ret != OK) { 340 ret = NO_MEMORY; 341 ALOGE("%s : No memory for m_pJpegOutputMem", __func__); 342 goto on_error; 343 } 344 jpeg_mem = m_pJpegOutputMem->getMemory(0, false); 345 if (NULL == jpeg_mem) { 346 ret = NO_MEMORY; 347 ALOGE("%s : initHeapMem for jpeg, ret = NO_MEMORY", __func__); 348 goto on_error; 349 } 350 encode_parm.num_dst_bufs = 1; 351 encode_parm.dest_buf[0].index = 0; 352 encode_parm.dest_buf[0].buf_size = jpeg_mem->size; 353 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)jpeg_mem->data; 354 encode_parm.dest_buf[0].fd = m_pJpegOutputMem->getFd(0); 355 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV; 356 encode_parm.dest_buf[0].offset = main_offset; 357 358 ALOGV("%s : X", __func__); 359 return NO_ERROR; 360 361 on_error: 362 if (m_pJpegOutputMem != NULL) { 363 m_pJpegOutputMem->deallocate(); 364 delete m_pJpegOutputMem; 365 m_pJpegOutputMem = NULL; 366 } 367 if (m_pJpegExifObj != NULL) { 368 delete m_pJpegExifObj; 369 m_pJpegExifObj = NULL; 370 } 371 ALOGV("%s : X with error %d", __func__, ret); 372 return ret; 373 } 374 375 /*=========================================================================== 376 * FUNCTION : sendEvtNotify 377 * 378 * DESCRIPTION: send event notify through notify callback registered by upper layer 379 * 380 * PARAMETERS : 381 * @msg_type: msg type of notify 382 * @ext1 : extension 383 * @ext2 : extension 384 * 385 * RETURN : int32_t type of status 386 * NO_ERROR -- success 387 * none-zero failure code 388 *==========================================================================*/ 389 int32_t QCameraPostProcessor::sendEvtNotify(int32_t msg_type, 390 int32_t ext1, 391 int32_t ext2) 392 { 393 return m_parent->sendEvtNotify(msg_type, ext1, ext2); 394 } 395 396 /*=========================================================================== 397 * FUNCTION : sendDataNotify 398 * 399 * DESCRIPTION: enqueue data into dataNotify thread 400 * 401 * PARAMETERS : 402 * @msg_type: data callback msg type 403 * @data : ptr to data memory struct 404 * @index : index to data buffer 405 * @metadata: ptr to meta data buffer if there is any 406 * @release_data : ptr to struct indicating if data need to be released 407 * after notify 408 * 409 * RETURN : int32_t type of status 410 * NO_ERROR -- success 411 * none-zero failure code 412 *==========================================================================*/ 413 int32_t QCameraPostProcessor::sendDataNotify(int32_t msg_type, 414 camera_memory_t *data, 415 uint8_t index, 416 camera_frame_metadata_t *metadata, 417 qcamera_release_data_t *release_data) 418 { 419 qcamera_data_argm_t *data_cb = (qcamera_data_argm_t *)malloc(sizeof(qcamera_data_argm_t)); 420 if (NULL == data_cb) { 421 ALOGE("%s: no mem for acamera_data_argm_t", __func__); 422 return NO_MEMORY; 423 } 424 memset(data_cb, 0, sizeof(qcamera_data_argm_t)); 425 data_cb->msg_type = msg_type; 426 data_cb->data = data; 427 data_cb->index = index; 428 data_cb->metadata = metadata; 429 if (release_data != NULL) { 430 data_cb->release_data = *release_data; 431 } 432 433 qcamera_callback_argm_t cbArg; 434 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 435 cbArg.cb_type = QCAMERA_DATA_SNAPSHOT_CALLBACK; 436 cbArg.msg_type = msg_type; 437 cbArg.data = data; 438 cbArg.metadata = metadata; 439 cbArg.user_data = data_cb; 440 cbArg.cookie = this; 441 cbArg.release_cb = releaseNotifyData; 442 int rc = m_parent->m_cbNotifier.notifyCallback(cbArg); 443 if ( NO_ERROR != rc ) { 444 ALOGE("%s: Error enqueuing jpeg data into notify queue", __func__); 445 free(data_cb); 446 return UNKNOWN_ERROR; 447 } 448 449 return rc; 450 } 451 452 /*=========================================================================== 453 * FUNCTION : processData 454 * 455 * DESCRIPTION: enqueue data into dataProc thread 456 * 457 * PARAMETERS : 458 * @frame : process frame received from mm-camera-interface 459 * 460 * RETURN : int32_t type of status 461 * NO_ERROR -- success 462 * none-zero failure code 463 * 464 * NOTE : depends on if offline reprocess is needed, received frame will 465 * be sent to either input queue of postprocess or jpeg encoding 466 *==========================================================================*/ 467 int32_t QCameraPostProcessor::processData(mm_camera_super_buf_t *frame) 468 { 469 if (m_parent->needReprocess()) { 470 ALOGD("%s: need reprocess", __func__); 471 // enqueu to post proc input queue 472 m_inputPPQ.enqueue((void *)frame); 473 } else if (m_parent->mParameters.isNV16PictureFormat()) { 474 processRawData(frame); 475 } else { 476 ALOGD("%s: no need offline reprocess, sending to jpeg encoding", __func__); 477 qcamera_jpeg_data_t *jpeg_job = 478 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t)); 479 if (jpeg_job == NULL) { 480 ALOGE("%s: No memory for jpeg job", __func__); 481 return NO_MEMORY; 482 } 483 484 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t)); 485 jpeg_job->src_frame = frame; 486 487 // enqueu to jpeg input queue 488 m_inputJpegQ.enqueue((void *)jpeg_job); 489 } 490 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 491 492 return NO_ERROR; 493 } 494 495 /*=========================================================================== 496 * FUNCTION : processRawData 497 * 498 * DESCRIPTION: enqueue raw data into dataProc thread 499 * 500 * PARAMETERS : 501 * @frame : process frame received from mm-camera-interface 502 * 503 * RETURN : int32_t type of status 504 * NO_ERROR -- success 505 * none-zero failure code 506 *==========================================================================*/ 507 int32_t QCameraPostProcessor::processRawData(mm_camera_super_buf_t *frame) 508 { 509 // enqueu to raw input queue 510 m_inputRawQ.enqueue((void *)frame); 511 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 512 return NO_ERROR; 513 } 514 515 /*=========================================================================== 516 * FUNCTION : processJpegEvt 517 * 518 * DESCRIPTION: process jpeg event from mm-jpeg-interface. 519 * 520 * PARAMETERS : 521 * @evt : payload of jpeg event, including information about jpeg encoding 522 * status, jpeg size and so on. 523 * 524 * RETURN : int32_t type of status 525 * NO_ERROR -- success 526 * none-zero failure code 527 * 528 * NOTE : This event will also trigger DataProc thread to move to next job 529 * processing (i.e., send a new jpeg encoding job to mm-jpeg-interface 530 * if there is any pending job in jpeg input queue) 531 *==========================================================================*/ 532 int32_t QCameraPostProcessor::processJpegEvt(qcamera_jpeg_evt_payload_t *evt) 533 { 534 int32_t rc = NO_ERROR; 535 camera_memory_t *jpeg_mem = NULL; 536 537 // find job by jobId 538 qcamera_jpeg_data_t *job = findJpegJobByJobId(evt->jobId); 539 540 if (job == NULL) { 541 ALOGE("%s: Cannot find jpeg job by jobId(%d)", __func__, evt->jobId); 542 rc = BAD_VALUE; 543 goto end; 544 } 545 546 ALOGD("[KPI Perf] %s : jpeg job %d", __func__, evt->jobId); 547 548 if (m_parent->mDataCb == NULL || 549 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) == 0 ) { 550 ALOGD("%s: No dataCB or CAMERA_MSG_COMPRESSED_IMAGE not enabled", 551 __func__); 552 rc = NO_ERROR; 553 goto end; 554 } 555 556 if(evt->status == JPEG_JOB_STATUS_ERROR) { 557 ALOGE("%s: Error event handled from jpeg, status = %d", 558 __func__, evt->status); 559 rc = FAILED_TRANSACTION; 560 goto end; 561 } 562 563 m_parent->dumpFrameToFile(evt->out_data.buf_vaddr, 564 evt->out_data.buf_filled_len, 565 evt->jobId, 566 QCAMERA_DUMP_FRM_JPEG); 567 ALOGD("%s: Dump jpeg_size=%d", __func__, evt->out_data.buf_filled_len); 568 569 // alloc jpeg memory to pass to upper layer 570 jpeg_mem = m_parent->mGetMemory(-1, evt->out_data.buf_filled_len, 1, m_parent->mCallbackCookie); 571 if (NULL == jpeg_mem) { 572 rc = NO_MEMORY; 573 ALOGE("%s : getMemory for jpeg, ret = NO_MEMORY", __func__); 574 goto end; 575 } 576 memcpy(jpeg_mem->data, evt->out_data.buf_vaddr, evt->out_data.buf_filled_len); 577 578 ALOGE("%s : Calling upperlayer callback to store JPEG image", __func__); 579 qcamera_release_data_t release_data; 580 memset(&release_data, 0, sizeof(qcamera_release_data_t)); 581 release_data.data = jpeg_mem; 582 rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 583 jpeg_mem, 584 0, 585 NULL, 586 &release_data); 587 588 end: 589 if (rc != NO_ERROR) { 590 // send error msg to upper layer 591 sendEvtNotify(CAMERA_MSG_ERROR, 592 UNKNOWN_ERROR, 593 0); 594 595 if (NULL != jpeg_mem) { 596 jpeg_mem->release(jpeg_mem); 597 jpeg_mem = NULL; 598 } 599 } 600 601 // release internal data for jpeg job 602 if (job != NULL) { 603 releaseJpegJobData(job); 604 free(job); 605 } 606 607 // wait up data proc thread to do next job, 608 // if previous request is blocked due to ongoing jpeg job 609 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 610 611 return rc; 612 } 613 614 /*=========================================================================== 615 * FUNCTION : processPPData 616 * 617 * DESCRIPTION: process received frame after reprocess. 618 * 619 * PARAMETERS : 620 * @frame : received frame from reprocess channel. 621 * 622 * RETURN : int32_t type of status 623 * NO_ERROR -- success 624 * none-zero failure code 625 * 626 * NOTE : The frame after reprocess need to send to jpeg encoding. 627 *==========================================================================*/ 628 int32_t QCameraPostProcessor::processPPData(mm_camera_super_buf_t *frame) 629 { 630 qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue(); 631 632 if (job == NULL || job->src_frame == NULL) { 633 ALOGE("%s: Cannot find reprocess job", __func__); 634 return BAD_VALUE; 635 } 636 637 if (m_parent->mParameters.isNV16PictureFormat()) { 638 releaseSuperBuf(job->src_frame); 639 free(job->src_frame); 640 free(job); 641 return processRawData(frame); 642 } 643 644 qcamera_jpeg_data_t *jpeg_job = 645 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t)); 646 if (jpeg_job == NULL) { 647 ALOGE("%s: No memory for jpeg job", __func__); 648 return NO_MEMORY; 649 } 650 651 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t)); 652 jpeg_job->src_frame = frame; 653 jpeg_job->src_reproc_frame = job->src_frame; 654 655 // free pp job buf 656 free(job); 657 658 // enqueu reprocessed frame to jpeg input queue 659 m_inputJpegQ.enqueue((void *)jpeg_job); 660 661 // wait up data proc thread 662 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 663 664 return NO_ERROR; 665 } 666 667 /*=========================================================================== 668 * FUNCTION : findJpegJobByJobId 669 * 670 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID 671 * 672 * PARAMETERS : 673 * @jobId : job Id of the job 674 * 675 * RETURN : ptr to a jpeg job struct. NULL if not found. 676 * 677 * NOTE : Currently only one job is sending to mm-jpeg-interface for jpeg 678 * encoding. Therefore simply dequeue from the ongoing Jpeg Queue 679 * will serve the purpose to find the jpeg job. 680 *==========================================================================*/ 681 qcamera_jpeg_data_t *QCameraPostProcessor::findJpegJobByJobId(uint32_t jobId) 682 { 683 qcamera_jpeg_data_t * job = NULL; 684 if (jobId == 0) { 685 ALOGE("%s: not a valid jpeg jobId", __func__); 686 return NULL; 687 } 688 689 // currely only one jpeg job ongoing, so simply dequeue the head 690 job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue(); 691 return job; 692 } 693 694 /*=========================================================================== 695 * FUNCTION : releasePPInputData 696 * 697 * DESCRIPTION: callback function to release post process input data node 698 * 699 * PARAMETERS : 700 * @data : ptr to post process input data 701 * @user_data : user data ptr (QCameraReprocessor) 702 * 703 * RETURN : None 704 *==========================================================================*/ 705 void QCameraPostProcessor::releasePPInputData(void *data, void *user_data) 706 { 707 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data; 708 if (NULL != pme) { 709 pme->releaseSuperBuf((mm_camera_super_buf_t *)data); 710 } 711 } 712 713 /*=========================================================================== 714 * FUNCTION : releaseJpegData 715 * 716 * DESCRIPTION: callback function to release jpeg job node 717 * 718 * PARAMETERS : 719 * @data : ptr to ongoing jpeg job data 720 * @user_data : user data ptr (QCameraReprocessor) 721 * 722 * RETURN : None 723 *==========================================================================*/ 724 void QCameraPostProcessor::releaseJpegData(void *data, void *user_data) 725 { 726 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data; 727 if (NULL != pme) { 728 pme->releaseJpegJobData((qcamera_jpeg_data_t *)data); 729 } 730 } 731 732 /*=========================================================================== 733 * FUNCTION : releaseOngoingPPData 734 * 735 * DESCRIPTION: callback function to release ongoing postprocess job node 736 * 737 * PARAMETERS : 738 * @data : ptr to onging postprocess job 739 * @user_data : user data ptr (QCameraReprocessor) 740 * 741 * RETURN : None 742 *==========================================================================*/ 743 void QCameraPostProcessor::releaseOngoingPPData(void *data, void *user_data) 744 { 745 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data; 746 if (NULL != pme) { 747 qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data; 748 if (NULL != pp_job->src_frame) { 749 pme->releaseSuperBuf(pp_job->src_frame); 750 free(pp_job->src_frame); 751 pp_job->src_frame = NULL; 752 } 753 } 754 } 755 756 /*=========================================================================== 757 * FUNCTION : releaseNotifyData 758 * 759 * DESCRIPTION: function to release internal resources in notify data struct 760 * 761 * PARAMETERS : 762 * @user_data : ptr user data 763 * @cookie : callback cookie 764 * 765 * RETURN : None 766 * 767 * NOTE : deallocate jpeg heap memory if it's not NULL 768 *==========================================================================*/ 769 void QCameraPostProcessor::releaseNotifyData(void *user_data, void *cookie) 770 { 771 qcamera_data_argm_t *app_cb = ( qcamera_data_argm_t * ) user_data; 772 QCameraPostProcessor *postProc = ( QCameraPostProcessor * ) cookie; 773 if ( ( NULL != app_cb ) && ( NULL != postProc ) ) { 774 if (app_cb && NULL != app_cb->release_data.data) { 775 app_cb->release_data.data->release(app_cb->release_data.data); 776 app_cb->release_data.data = NULL; 777 } 778 if (app_cb && NULL != app_cb->release_data.frame) { 779 postProc->releaseSuperBuf(app_cb->release_data.frame); 780 free(app_cb->release_data.frame); 781 app_cb->release_data.frame = NULL; 782 } 783 free(app_cb); 784 } 785 } 786 787 /*=========================================================================== 788 * FUNCTION : releaseSuperBuf 789 * 790 * DESCRIPTION: function to release a superbuf frame by returning back to kernel 791 * 792 * PARAMETERS : 793 * @super_buf : ptr to the superbuf frame 794 * 795 * RETURN : None 796 *==========================================================================*/ 797 void QCameraPostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf) 798 { 799 QCameraChannel *pChannel = NULL; 800 801 if (NULL != super_buf) { 802 pChannel = m_parent->getChannelByHandle(super_buf->ch_id); 803 804 if ( NULL == pChannel ) { 805 if (m_pReprocChannel != NULL && 806 m_pReprocChannel->getMyHandle() == super_buf->ch_id) { 807 pChannel = m_pReprocChannel; 808 } 809 } 810 811 if (pChannel != NULL) { 812 pChannel->bufDone(super_buf); 813 } else { 814 ALOGE(" %s : Channel id %d not found!!", 815 __func__, 816 super_buf->ch_id); 817 } 818 } 819 } 820 821 /*=========================================================================== 822 * FUNCTION : releaseJpegJobData 823 * 824 * DESCRIPTION: function to release internal resources in jpeg job struct 825 * 826 * PARAMETERS : 827 * @job : ptr to jpeg job struct 828 * 829 * RETURN : None 830 * 831 * NOTE : original source frame need to be queued back to kernel for 832 * future use. Output buf of jpeg job need to be released since 833 * it's allocated for each job. Exif object need to be deleted. 834 *==========================================================================*/ 835 void QCameraPostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job) 836 { 837 ALOGV("%s: E", __func__); 838 if (NULL != job) { 839 if (NULL != job->src_reproc_frame) { 840 releaseSuperBuf(job->src_reproc_frame); 841 free(job->src_reproc_frame); 842 job->src_reproc_frame = NULL; 843 } 844 845 if (NULL != job->src_frame) { 846 releaseSuperBuf(job->src_frame); 847 free(job->src_frame); 848 job->src_frame = NULL; 849 } 850 } 851 ALOGV("%s: X", __func__); 852 } 853 854 /*=========================================================================== 855 * FUNCTION : getColorfmtFromImgFmt 856 * 857 * DESCRIPTION: function to return jpeg color format based on its image format 858 * 859 * PARAMETERS : 860 * @img_fmt : image format 861 * 862 * RETURN : jpeg color format that can be understandable by omx lib 863 *==========================================================================*/ 864 mm_jpeg_color_format QCameraPostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt) 865 { 866 switch (img_fmt) { 867 case CAM_FORMAT_YUV_420_NV21: 868 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 869 case CAM_FORMAT_YUV_420_NV21_ADRENO: 870 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 871 case CAM_FORMAT_YUV_420_NV12: 872 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 873 case CAM_FORMAT_YUV_420_YV12: 874 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 875 case CAM_FORMAT_YUV_422_NV61: 876 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1; 877 case CAM_FORMAT_YUV_422_NV16: 878 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1; 879 default: 880 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 881 } 882 } 883 884 /*=========================================================================== 885 * FUNCTION : getJpegImgTypeFromImgFmt 886 * 887 * DESCRIPTION: function to return jpeg encode image type based on its image format 888 * 889 * PARAMETERS : 890 * @img_fmt : image format 891 * 892 * RETURN : return jpeg source image format (YUV or Bitstream) 893 *==========================================================================*/ 894 mm_jpeg_format_t QCameraPostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt) 895 { 896 switch (img_fmt) { 897 case CAM_FORMAT_YUV_420_NV21: 898 case CAM_FORMAT_YUV_420_NV21_ADRENO: 899 case CAM_FORMAT_YUV_420_NV12: 900 case CAM_FORMAT_YUV_420_YV12: 901 case CAM_FORMAT_YUV_422_NV61: 902 case CAM_FORMAT_YUV_422_NV16: 903 return MM_JPEG_FMT_YUV; 904 default: 905 return MM_JPEG_FMT_YUV; 906 } 907 } 908 909 /*=========================================================================== 910 * FUNCTION : encodeData 911 * 912 * DESCRIPTION: function to prepare encoding job information and send to 913 * mm-jpeg-interface to do the encoding job 914 * 915 * PARAMETERS : 916 * @jpeg_job_data : ptr to a struct saving job related information 917 * @needNewSess : flag to indicate if a new jpeg encoding session need 918 * to be created. After creation, this flag will be toggled 919 * 920 * RETURN : int32_t type of status 921 * NO_ERROR -- success 922 * none-zero failure code 923 *==========================================================================*/ 924 int32_t QCameraPostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data, 925 uint8_t &needNewSess) 926 { 927 ALOGV("%s : E", __func__); 928 int32_t ret = NO_ERROR; 929 mm_jpeg_job_t jpg_job; 930 uint32_t jobId = 0; 931 QCameraStream *main_stream = NULL; 932 mm_camera_buf_def_t *main_frame = NULL; 933 QCameraStream *thumb_stream = NULL; 934 mm_camera_buf_def_t *thumb_frame = NULL; 935 mm_camera_super_buf_t *recvd_frame = jpeg_job_data->src_frame; 936 937 // find channel 938 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id); 939 // check reprocess channel if not found 940 if (pChannel == NULL) { 941 if (m_pReprocChannel != NULL && 942 m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) { 943 pChannel = m_pReprocChannel; 944 } 945 } 946 if (pChannel == NULL) { 947 ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here", 948 __func__, recvd_frame->ch_id); 949 return BAD_VALUE; 950 } 951 952 // find snapshot frame and thumnail frame 953 for (int i = 0; i < recvd_frame->num_bufs; i++) { 954 QCameraStream *pStream = 955 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id); 956 if (pStream != NULL) { 957 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 958 pStream->isTypeOf(CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT) || 959 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 960 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT)) { 961 main_stream = pStream; 962 main_frame = recvd_frame->bufs[i]; 963 } else if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 964 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 965 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) || 966 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) { 967 thumb_stream = pStream; 968 thumb_frame = recvd_frame->bufs[i]; 969 } 970 } 971 } 972 973 if(NULL == main_frame){ 974 ALOGE("%s : Main frame is NULL", __func__); 975 return BAD_VALUE; 976 } 977 978 QCameraMemory *memObj = (QCameraMemory *)main_frame->mem_info; 979 if (NULL == memObj) { 980 ALOGE("%s : Memeory Obj of main frame is NULL", __func__); 981 return NO_MEMORY; 982 } 983 984 // dump snapshot frame if enabled 985 m_parent->dumpFrameToFile(main_frame->buffer, main_frame->frame_len, 986 main_frame->frame_idx, QCAMERA_DUMP_FRM_SNAPSHOT); 987 988 // send upperlayer callback for raw image 989 camera_memory_t *mem = memObj->getMemory(main_frame->buf_idx, false); 990 if (NULL != m_parent->mDataCb && 991 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) { 992 qcamera_callback_argm_t cbArg; 993 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 994 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 995 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE; 996 cbArg.data = mem; 997 cbArg.index = 1; 998 m_parent->m_cbNotifier.notifyCallback(cbArg); 999 } 1000 if (NULL != m_parent->mNotifyCb && 1001 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) { 1002 qcamera_callback_argm_t cbArg; 1003 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 1004 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; 1005 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY; 1006 cbArg.ext1 = 0; 1007 cbArg.ext2 = 0; 1008 m_parent->m_cbNotifier.notifyCallback(cbArg); 1009 } 1010 1011 if (thumb_frame != NULL) { 1012 // dump thumbnail frame if enabled 1013 m_parent->dumpFrameToFile(thumb_frame->buffer, thumb_frame->frame_len, 1014 thumb_frame->frame_idx, QCAMERA_DUMP_FRM_THUMBNAIL); 1015 } 1016 1017 if (mJpegClientHandle <= 0) { 1018 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__); 1019 return UNKNOWN_ERROR; 1020 } 1021 1022 if (needNewSess) { 1023 // create jpeg encoding session 1024 mm_jpeg_encode_params_t encodeParam; 1025 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t)); 1026 getJpegEncodingConfig(encodeParam, main_stream, thumb_stream); 1027 ALOGD("[KPI Perf] %s : call jpeg create_session", __func__); 1028 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId); 1029 if (ret != NO_ERROR) { 1030 ALOGE("%s: error creating a new jpeg encoding session", __func__); 1031 return ret; 1032 } 1033 needNewSess = FALSE; 1034 } 1035 1036 // Fill in new job 1037 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t)); 1038 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE; 1039 jpg_job.encode_job.session_id = mJpegSessionId; 1040 jpg_job.encode_job.src_index = main_frame->buf_idx; 1041 jpg_job.encode_job.dst_index = 0; 1042 1043 cam_rect_t crop; 1044 memset(&crop, 0, sizeof(cam_rect_t)); 1045 main_stream->getCropInfo(crop); 1046 1047 cam_dimension_t src_dim; 1048 memset(&src_dim, 0, sizeof(cam_dimension_t)); 1049 main_stream->getFrameDimension(src_dim); 1050 1051 // main dim 1052 jpg_job.encode_job.main_dim.src_dim = src_dim; 1053 jpg_job.encode_job.main_dim.dst_dim = src_dim; 1054 jpg_job.encode_job.main_dim.crop = crop; 1055 1056 // thumbnail dim 1057 if (m_bThumbnailNeeded == TRUE) { 1058 if (thumb_stream == NULL) { 1059 // need jpeg thumbnail, but no postview/preview stream exists 1060 // we use the main stream/frame to encode thumbnail 1061 thumb_stream = main_stream; 1062 thumb_frame = main_frame; 1063 } 1064 memset(&crop, 0, sizeof(cam_rect_t)); 1065 thumb_stream->getCropInfo(crop); 1066 memset(&src_dim, 0, sizeof(cam_dimension_t)); 1067 thumb_stream->getFrameDimension(src_dim); 1068 jpg_job.encode_job.thumb_dim.src_dim = src_dim; 1069 m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim); 1070 int rotation = m_parent->getJpegRotation(); 1071 if (rotation == 90 || rotation ==270) { 1072 // swap dimension if rotation is 90 or 270 1073 int32_t temp = jpg_job.encode_job.thumb_dim.dst_dim.height; 1074 jpg_job.encode_job.thumb_dim.dst_dim.height = 1075 jpg_job.encode_job.thumb_dim.dst_dim.width; 1076 jpg_job.encode_job.thumb_dim.dst_dim.width = temp; 1077 } 1078 jpg_job.encode_job.thumb_dim.crop = crop; 1079 jpg_job.encode_job.thumb_index = thumb_frame->buf_idx; 1080 } 1081 1082 // set rotation only when no online rotation or offline pp rotation is done before 1083 if (!m_parent->needRotationReprocess()) { 1084 jpg_job.encode_job.rotation = m_parent->getJpegRotation(); 1085 } 1086 ALOGV("%s: jpeg rotation is set to %d", __func__, jpg_job.encode_job.rotation); 1087 1088 // find meta data frame 1089 mm_camera_buf_def_t *meta_frame = NULL; 1090 for (int i = 0; i < jpeg_job_data->src_frame->num_bufs; i++) { 1091 // look through input superbuf 1092 if (jpeg_job_data->src_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 1093 meta_frame = jpeg_job_data->src_frame->bufs[i]; 1094 break; 1095 } 1096 } 1097 if (meta_frame == NULL && jpeg_job_data->src_reproc_frame != NULL) { 1098 // look through reprocess source superbuf 1099 for (int i = 0; i < jpeg_job_data->src_reproc_frame->num_bufs; i++) { 1100 if (jpeg_job_data->src_reproc_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 1101 meta_frame = jpeg_job_data->src_reproc_frame->bufs[i]; 1102 break; 1103 } 1104 } 1105 } 1106 if (meta_frame != NULL) { 1107 // fill in meta data frame ptr 1108 jpg_job.encode_job.p_metadata_v1 = (cam_metadata_info_t *)meta_frame->buffer; 1109 } 1110 1111 ALOGD("[KPI Perf] %s : call jpeg start_job", __func__); 1112 ret = mJpegHandle.start_job(&jpg_job, &jobId); 1113 if (ret == NO_ERROR) { 1114 // remember job info 1115 jpeg_job_data->jobId = jobId; 1116 } 1117 1118 return ret; 1119 } 1120 1121 /*=========================================================================== 1122 * FUNCTION : processRawImageImpl 1123 * 1124 * DESCRIPTION: function to send raw image to upper layer 1125 * 1126 * PARAMETERS : 1127 * @recvd_frame : frame to be encoded 1128 * 1129 * RETURN : int32_t type of status 1130 * NO_ERROR -- success 1131 * none-zero failure code 1132 *==========================================================================*/ 1133 int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_frame) 1134 { 1135 int32_t rc = NO_ERROR; 1136 1137 mm_camera_buf_def_t *frame = NULL; 1138 for ( int i= 0 ; i < recvd_frame->num_bufs ; i++ ) { 1139 if ( recvd_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_SNAPSHOT || 1140 recvd_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT || 1141 recvd_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_RAW ) { 1142 frame = recvd_frame->bufs[i]; 1143 break; 1144 } 1145 } 1146 if ( NULL == frame ) { 1147 ALOGE("%s: No valid raw buffer", __func__); 1148 return BAD_VALUE; 1149 } 1150 1151 QCameraMemory *rawMemObj = (QCameraMemory *)frame->mem_info; 1152 camera_memory_t *raw_mem = NULL; 1153 1154 if (rawMemObj != NULL) { 1155 raw_mem = rawMemObj->getMemory(frame->buf_idx, false); 1156 } 1157 1158 if (NULL != rawMemObj && NULL != raw_mem) { 1159 // dump frame into file 1160 m_parent->dumpFrameToFile(frame->buffer, frame->frame_len, 1161 frame->frame_idx, QCAMERA_DUMP_FRM_RAW); 1162 1163 // send data callback / notify for RAW_IMAGE 1164 if (NULL != m_parent->mDataCb && 1165 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) { 1166 qcamera_callback_argm_t cbArg; 1167 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 1168 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 1169 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE; 1170 cbArg.data = raw_mem; 1171 cbArg.index = 0; 1172 m_parent->m_cbNotifier.notifyCallback(cbArg); 1173 } 1174 if (NULL != m_parent->mNotifyCb && 1175 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) { 1176 qcamera_callback_argm_t cbArg; 1177 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 1178 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; 1179 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY; 1180 cbArg.ext1 = 0; 1181 cbArg.ext2 = 0; 1182 m_parent->m_cbNotifier.notifyCallback(cbArg); 1183 } 1184 1185 if ((m_parent->mDataCb != NULL) && 1186 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) > 0) { 1187 qcamera_release_data_t release_data; 1188 memset(&release_data, 0, sizeof(qcamera_release_data_t)); 1189 release_data.frame = recvd_frame; 1190 sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 1191 raw_mem, 1192 0, 1193 NULL, 1194 &release_data); 1195 } 1196 } else { 1197 ALOGE("%s: Cannot get raw mem", __func__); 1198 rc = UNKNOWN_ERROR; 1199 } 1200 1201 return rc; 1202 } 1203 1204 /*=========================================================================== 1205 * FUNCTION : dataProcessRoutine 1206 * 1207 * DESCRIPTION: data process routine that handles input data either from input 1208 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do 1209 * reprocess. 1210 * 1211 * PARAMETERS : 1212 * @data : user data ptr (QCameraPostProcessor) 1213 * 1214 * RETURN : None 1215 *==========================================================================*/ 1216 void *QCameraPostProcessor::dataProcessRoutine(void *data) 1217 { 1218 int running = 1; 1219 int ret; 1220 uint8_t is_active = FALSE; 1221 uint8_t needNewSess = TRUE; 1222 QCameraPostProcessor *pme = (QCameraPostProcessor *)data; 1223 QCameraCmdThread *cmdThread = &pme->m_dataProcTh; 1224 1225 ALOGD("%s: E", __func__); 1226 do { 1227 do { 1228 ret = cam_sem_wait(&cmdThread->cmd_sem); 1229 if (ret != 0 && errno != EINVAL) { 1230 ALOGE("%s: cam_sem_wait error (%s)", 1231 __func__, strerror(errno)); 1232 return NULL; 1233 } 1234 } while (ret != 0); 1235 1236 // we got notified about new cmd avail in cmd queue 1237 camera_cmd_type_t cmd = cmdThread->getCmd(); 1238 switch (cmd) { 1239 case CAMERA_CMD_TYPE_START_DATA_PROC: 1240 ALOGD("%s: start data proc", __func__); 1241 is_active = TRUE; 1242 needNewSess = TRUE; 1243 break; 1244 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 1245 { 1246 ALOGD("%s: stop data proc", __func__); 1247 is_active = FALSE; 1248 1249 // cancel all ongoing jpeg jobs 1250 qcamera_jpeg_data_t *jpeg_job = 1251 (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1252 while (jpeg_job != NULL) { 1253 pme->mJpegHandle.abort_job(jpeg_job->jobId); 1254 1255 pme->releaseJpegJobData(jpeg_job); 1256 free(jpeg_job); 1257 1258 jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1259 } 1260 1261 // destroy jpeg encoding session 1262 if ( 0 < pme->mJpegSessionId ) { 1263 pme->mJpegHandle.destroy_session(pme->mJpegSessionId); 1264 pme->mJpegSessionId = 0; 1265 } 1266 1267 // free jpeg out buf and exif obj 1268 if (pme->m_pJpegOutputMem != NULL) { 1269 pme->m_pJpegOutputMem->deallocate(); 1270 delete pme->m_pJpegOutputMem; 1271 pme->m_pJpegOutputMem = NULL; 1272 } 1273 if (pme->m_pJpegExifObj != NULL) { 1274 delete pme->m_pJpegExifObj; 1275 pme->m_pJpegExifObj = NULL; 1276 } 1277 needNewSess = TRUE; 1278 1279 // stop reproc channel if exists 1280 if (pme->m_pReprocChannel != NULL) { 1281 pme->m_pReprocChannel->stop(); 1282 delete pme->m_pReprocChannel; 1283 pme->m_pReprocChannel = NULL; 1284 } 1285 1286 // flush ongoing postproc Queue 1287 pme->m_ongoingPPQ.flush(); 1288 1289 // flush input jpeg Queue 1290 pme->m_inputJpegQ.flush(); 1291 1292 // flush input Postproc Queue 1293 pme->m_inputPPQ.flush(); 1294 1295 // flush input raw Queue 1296 pme->m_inputRawQ.flush(); 1297 1298 // signal cmd is completed 1299 cam_sem_post(&cmdThread->sync_sem); 1300 } 1301 break; 1302 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 1303 { 1304 ALOGD("%s: Do next job, active is %d", __func__, is_active); 1305 if (is_active == TRUE) { 1306 // check if there is any ongoing jpeg jobs 1307 if (pme->m_ongoingJpegQ.isEmpty()) { 1308 // no ongoing jpeg job, we are fine to send jpeg encoding job 1309 qcamera_jpeg_data_t *jpeg_job = 1310 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 1311 1312 if (NULL != jpeg_job) { 1313 //play shutter sound 1314 pme->m_parent->playShutter(); 1315 1316 // add into ongoing jpeg job Q 1317 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job); 1318 ret = pme->encodeData(jpeg_job, needNewSess); 1319 if (NO_ERROR != ret) { 1320 // dequeue the last one 1321 pme->m_ongoingJpegQ.dequeue(false); 1322 1323 pme->releaseJpegJobData(jpeg_job); 1324 free(jpeg_job); 1325 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 1326 } 1327 } 1328 } 1329 1330 // process raw data if any 1331 mm_camera_super_buf_t *super_buf = 1332 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 1333 1334 if (NULL != super_buf) { 1335 //play shutter sound 1336 pme->m_parent->playShutter(); 1337 ret = pme->processRawImageImpl(super_buf); 1338 if (NO_ERROR != ret) { 1339 pme->releaseSuperBuf(super_buf); 1340 free(super_buf); 1341 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 1342 } 1343 } 1344 1345 mm_camera_super_buf_t *pp_frame = 1346 (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 1347 if (NULL != pp_frame) { 1348 qcamera_pp_data_t *pp_job = 1349 (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t)); 1350 if (pp_job != NULL) { 1351 memset(pp_job, 0, sizeof(qcamera_pp_data_t)); 1352 if (pme->m_pReprocChannel != NULL) { 1353 // add into ongoing PP job Q 1354 pp_job->src_frame = pp_frame; 1355 pme->m_ongoingPPQ.enqueue((void *)pp_job); 1356 ret = pme->m_pReprocChannel->doReprocess(pp_frame); 1357 if (NO_ERROR != ret) { 1358 // remove from ongoing PP job Q 1359 pme->m_ongoingPPQ.dequeue(false); 1360 } 1361 } else { 1362 ALOGE("%s: Reprocess channel is NULL", __func__); 1363 ret = -1; 1364 } 1365 } else { 1366 ALOGE("%s: no mem for qcamera_pp_data_t", __func__); 1367 ret = -1; 1368 } 1369 1370 if (0 != ret) { 1371 // free pp_job 1372 if (pp_job != NULL) { 1373 free(pp_job); 1374 } 1375 // free frame 1376 if (pp_frame != NULL) { 1377 pme->releaseSuperBuf(pp_frame); 1378 free(pp_frame); 1379 } 1380 // send error notify 1381 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 1382 } 1383 } 1384 } else { 1385 // not active, simply return buf and do no op 1386 qcamera_jpeg_data_t *jpeg_data = 1387 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 1388 if (NULL != jpeg_data) { 1389 pme->releaseJpegJobData(jpeg_data); 1390 free(jpeg_data); 1391 } 1392 mm_camera_super_buf_t *super_buf = 1393 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 1394 if (NULL != super_buf) { 1395 pme->releaseSuperBuf(super_buf); 1396 free(super_buf); 1397 } 1398 super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 1399 if (NULL != super_buf) { 1400 pme->releaseSuperBuf(super_buf); 1401 free(super_buf); 1402 } 1403 } 1404 } 1405 break; 1406 case CAMERA_CMD_TYPE_EXIT: 1407 running = 0; 1408 break; 1409 default: 1410 break; 1411 } 1412 } while (running); 1413 ALOGD("%s: X", __func__); 1414 return NULL; 1415 } 1416 1417 /*=========================================================================== 1418 * FUNCTION : getJpegPaddingReq 1419 * 1420 * DESCRIPTION: function to add an entry to exif data 1421 * 1422 * PARAMETERS : 1423 * @padding_info : jpeg specific padding requirement 1424 * 1425 * RETURN : int32_t type of status 1426 * NO_ERROR -- success 1427 * none-zero failure code 1428 *==========================================================================*/ 1429 int32_t QCameraPostProcessor::getJpegPaddingReq(cam_padding_info_t &padding_info) 1430 { 1431 // TODO: hardcode for now, needs to query from mm-jpeg-interface 1432 padding_info.width_padding = CAM_PAD_NONE; 1433 padding_info.height_padding = CAM_PAD_TO_16; 1434 padding_info.plane_padding = CAM_PAD_TO_WORD; 1435 return NO_ERROR; 1436 } 1437 1438 /*=========================================================================== 1439 * FUNCTION : QCameraExif 1440 * 1441 * DESCRIPTION: constructor of QCameraExif 1442 * 1443 * PARAMETERS : None 1444 * 1445 * RETURN : None 1446 *==========================================================================*/ 1447 QCameraExif::QCameraExif() 1448 : m_nNumEntries(0) 1449 { 1450 memset(m_Entries, 0, sizeof(m_Entries)); 1451 } 1452 1453 /*=========================================================================== 1454 * FUNCTION : ~QCameraExif 1455 * 1456 * DESCRIPTION: deconstructor of QCameraExif. Will release internal memory ptr. 1457 * 1458 * PARAMETERS : None 1459 * 1460 * RETURN : None 1461 *==========================================================================*/ 1462 QCameraExif::~QCameraExif() 1463 { 1464 for (uint32_t i = 0; i < m_nNumEntries; i++) { 1465 switch (m_Entries[i].tag_entry.type) { 1466 case EXIF_BYTE: 1467 { 1468 if (m_Entries[i].tag_entry.count > 1 && 1469 m_Entries[i].tag_entry.data._bytes != NULL) { 1470 free(m_Entries[i].tag_entry.data._bytes); 1471 m_Entries[i].tag_entry.data._bytes = NULL; 1472 } 1473 } 1474 break; 1475 case EXIF_ASCII: 1476 { 1477 if (m_Entries[i].tag_entry.data._ascii != NULL) { 1478 free(m_Entries[i].tag_entry.data._ascii); 1479 m_Entries[i].tag_entry.data._ascii = NULL; 1480 } 1481 } 1482 break; 1483 case EXIF_SHORT: 1484 { 1485 if (m_Entries[i].tag_entry.count > 1 && 1486 m_Entries[i].tag_entry.data._shorts != NULL) { 1487 free(m_Entries[i].tag_entry.data._shorts); 1488 m_Entries[i].tag_entry.data._shorts = NULL; 1489 } 1490 } 1491 break; 1492 case EXIF_LONG: 1493 { 1494 if (m_Entries[i].tag_entry.count > 1 && 1495 m_Entries[i].tag_entry.data._longs != NULL) { 1496 free(m_Entries[i].tag_entry.data._longs); 1497 m_Entries[i].tag_entry.data._longs = NULL; 1498 } 1499 } 1500 break; 1501 case EXIF_RATIONAL: 1502 { 1503 if (m_Entries[i].tag_entry.count > 1 && 1504 m_Entries[i].tag_entry.data._rats != NULL) { 1505 free(m_Entries[i].tag_entry.data._rats); 1506 m_Entries[i].tag_entry.data._rats = NULL; 1507 } 1508 } 1509 break; 1510 case EXIF_UNDEFINED: 1511 { 1512 if (m_Entries[i].tag_entry.data._undefined != NULL) { 1513 free(m_Entries[i].tag_entry.data._undefined); 1514 m_Entries[i].tag_entry.data._undefined = NULL; 1515 } 1516 } 1517 break; 1518 case EXIF_SLONG: 1519 { 1520 if (m_Entries[i].tag_entry.count > 1 && 1521 m_Entries[i].tag_entry.data._slongs != NULL) { 1522 free(m_Entries[i].tag_entry.data._slongs); 1523 m_Entries[i].tag_entry.data._slongs = NULL; 1524 } 1525 } 1526 break; 1527 case EXIF_SRATIONAL: 1528 { 1529 if (m_Entries[i].tag_entry.count > 1 && 1530 m_Entries[i].tag_entry.data._srats != NULL) { 1531 free(m_Entries[i].tag_entry.data._srats); 1532 m_Entries[i].tag_entry.data._srats = NULL; 1533 } 1534 } 1535 break; 1536 } 1537 } 1538 } 1539 1540 /*=========================================================================== 1541 * FUNCTION : addEntry 1542 * 1543 * DESCRIPTION: function to add an entry to exif data 1544 * 1545 * PARAMETERS : 1546 * @tagid : exif tag ID 1547 * @type : data type 1548 * @count : number of data in uint of its type 1549 * @data : input data ptr 1550 * 1551 * RETURN : int32_t type of status 1552 * NO_ERROR -- success 1553 * none-zero failure code 1554 *==========================================================================*/ 1555 int32_t QCameraExif::addEntry(exif_tag_id_t tagid, 1556 exif_tag_type_t type, 1557 uint32_t count, 1558 void *data) 1559 { 1560 int32_t rc = NO_ERROR; 1561 if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) { 1562 ALOGE("%s: Number of entries exceeded limit", __func__); 1563 return NO_MEMORY; 1564 } 1565 1566 m_Entries[m_nNumEntries].tag_id = tagid; 1567 m_Entries[m_nNumEntries].tag_entry.type = type; 1568 m_Entries[m_nNumEntries].tag_entry.count = count; 1569 m_Entries[m_nNumEntries].tag_entry.copy = 1; 1570 switch (type) { 1571 case EXIF_BYTE: 1572 { 1573 if (count > 1) { 1574 uint8_t *values = (uint8_t *)malloc(count); 1575 if (values == NULL) { 1576 ALOGE("%s: No memory for byte array", __func__); 1577 rc = NO_MEMORY; 1578 } else { 1579 memcpy(values, data, count); 1580 m_Entries[m_nNumEntries].tag_entry.data._bytes = values; 1581 } 1582 } else { 1583 m_Entries[m_nNumEntries].tag_entry.data._byte = *(uint8_t *)data; 1584 } 1585 } 1586 break; 1587 case EXIF_ASCII: 1588 { 1589 char *str = NULL; 1590 str = (char *)malloc(count + 1); 1591 if (str == NULL) { 1592 ALOGE("%s: No memory for ascii string", __func__); 1593 rc = NO_MEMORY; 1594 } else { 1595 memset(str, 0, count + 1); 1596 memcpy(str, data, count); 1597 m_Entries[m_nNumEntries].tag_entry.data._ascii = str; 1598 } 1599 } 1600 break; 1601 case EXIF_SHORT: 1602 { 1603 if (count > 1) { 1604 uint16_t *values = (uint16_t *)malloc(count * sizeof(uint16_t)); 1605 if (values == NULL) { 1606 ALOGE("%s: No memory for short array", __func__); 1607 rc = NO_MEMORY; 1608 } else { 1609 memcpy(values, data, count * sizeof(uint16_t)); 1610 m_Entries[m_nNumEntries].tag_entry.data._shorts = values; 1611 } 1612 } else { 1613 m_Entries[m_nNumEntries].tag_entry.data._short = *(uint16_t *)data; 1614 } 1615 } 1616 break; 1617 case EXIF_LONG: 1618 { 1619 if (count > 1) { 1620 uint32_t *values = (uint32_t *)malloc(count * sizeof(uint32_t)); 1621 if (values == NULL) { 1622 ALOGE("%s: No memory for long array", __func__); 1623 rc = NO_MEMORY; 1624 } else { 1625 memcpy(values, data, count * sizeof(uint32_t)); 1626 m_Entries[m_nNumEntries].tag_entry.data._longs = values; 1627 } 1628 } else { 1629 m_Entries[m_nNumEntries].tag_entry.data._long = *(uint32_t *)data; 1630 } 1631 } 1632 break; 1633 case EXIF_RATIONAL: 1634 { 1635 if (count > 1) { 1636 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t)); 1637 if (values == NULL) { 1638 ALOGE("%s: No memory for rational array", __func__); 1639 rc = NO_MEMORY; 1640 } else { 1641 memcpy(values, data, count * sizeof(rat_t)); 1642 m_Entries[m_nNumEntries].tag_entry.data._rats = values; 1643 } 1644 } else { 1645 m_Entries[m_nNumEntries].tag_entry.data._rat = *(rat_t *)data; 1646 } 1647 } 1648 break; 1649 case EXIF_UNDEFINED: 1650 { 1651 uint8_t *values = (uint8_t *)malloc(count); 1652 if (values == NULL) { 1653 ALOGE("%s: No memory for undefined array", __func__); 1654 rc = NO_MEMORY; 1655 } else { 1656 memcpy(values, data, count); 1657 m_Entries[m_nNumEntries].tag_entry.data._undefined = values; 1658 } 1659 } 1660 break; 1661 case EXIF_SLONG: 1662 { 1663 if (count > 1) { 1664 int32_t *values = (int32_t *)malloc(count * sizeof(int32_t)); 1665 if (values == NULL) { 1666 ALOGE("%s: No memory for signed long array", __func__); 1667 rc = NO_MEMORY; 1668 } else { 1669 memcpy(values, data, count * sizeof(int32_t)); 1670 m_Entries[m_nNumEntries].tag_entry.data._slongs = values; 1671 } 1672 } else { 1673 m_Entries[m_nNumEntries].tag_entry.data._slong = *(int32_t *)data; 1674 } 1675 } 1676 break; 1677 case EXIF_SRATIONAL: 1678 { 1679 if (count > 1) { 1680 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t)); 1681 if (values == NULL) { 1682 ALOGE("%s: No memory for signed rational array", __func__); 1683 rc = NO_MEMORY; 1684 } else { 1685 memcpy(values, data, count * sizeof(srat_t)); 1686 m_Entries[m_nNumEntries].tag_entry.data._srats = values; 1687 } 1688 } else { 1689 m_Entries[m_nNumEntries].tag_entry.data._srat = *(srat_t *)data; 1690 } 1691 } 1692 break; 1693 } 1694 1695 // Increase number of entries 1696 m_nNumEntries++; 1697 return rc; 1698 } 1699 1700 }; // namespace qcamera 1701