QCameraPostProc.cpp revision 744f5403bebb0e27140d16a5df7a341713c24a13
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 38namespace 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 *==========================================================================*/ 50QCameraPostProcessor::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 *==========================================================================*/ 78QCameraPostProcessor::~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 *==========================================================================*/ 109int32_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 *==========================================================================*/ 136int32_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 *==========================================================================*/ 167int32_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 *==========================================================================*/ 210int32_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 *==========================================================================*/ 231int32_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 361on_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 *==========================================================================*/ 389int32_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 *==========================================================================*/ 413int32_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 *==========================================================================*/ 467int32_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 *==========================================================================*/ 507int32_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 *==========================================================================*/ 532int32_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 588end: 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 *==========================================================================*/ 628int32_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 *==========================================================================*/ 681qcamera_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 *==========================================================================*/ 705void 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 *==========================================================================*/ 724void 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 *==========================================================================*/ 743void 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 *==========================================================================*/ 769void 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 *==========================================================================*/ 797void 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 *==========================================================================*/ 835void 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 *==========================================================================*/ 864mm_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 *==========================================================================*/ 894mm_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 *==========================================================================*/ 924int32_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->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { 959 main_stream = pStream; 960 main_frame = recvd_frame->bufs[i]; 961 } else if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 962 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) || 963 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) || 964 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) { 965 thumb_stream = pStream; 966 thumb_frame = recvd_frame->bufs[i]; 967 } 968 } 969 } 970 971 if(NULL == main_frame){ 972 ALOGE("%s : Main frame is NULL", __func__); 973 return BAD_VALUE; 974 } 975 976 QCameraMemory *memObj = (QCameraMemory *)main_frame->mem_info; 977 if (NULL == memObj) { 978 ALOGE("%s : Memeory Obj of main frame is NULL", __func__); 979 return NO_MEMORY; 980 } 981 982 // dump snapshot frame if enabled 983 m_parent->dumpFrameToFile(main_frame->buffer, main_frame->frame_len, 984 main_frame->frame_idx, QCAMERA_DUMP_FRM_SNAPSHOT); 985 986 // send upperlayer callback for raw image 987 camera_memory_t *mem = memObj->getMemory(main_frame->buf_idx, false); 988 if (NULL != m_parent->mDataCb && 989 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) { 990 qcamera_callback_argm_t cbArg; 991 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 992 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 993 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE; 994 cbArg.data = mem; 995 cbArg.index = 1; 996 m_parent->m_cbNotifier.notifyCallback(cbArg); 997 } 998 if (NULL != m_parent->mNotifyCb && 999 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) { 1000 qcamera_callback_argm_t cbArg; 1001 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 1002 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; 1003 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY; 1004 cbArg.ext1 = 0; 1005 cbArg.ext2 = 0; 1006 m_parent->m_cbNotifier.notifyCallback(cbArg); 1007 } 1008 1009 if (thumb_frame != NULL) { 1010 // dump thumbnail frame if enabled 1011 m_parent->dumpFrameToFile(thumb_frame->buffer, thumb_frame->frame_len, 1012 thumb_frame->frame_idx, QCAMERA_DUMP_FRM_THUMBNAIL); 1013 } 1014 1015 if (mJpegClientHandle <= 0) { 1016 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__); 1017 return UNKNOWN_ERROR; 1018 } 1019 1020 if (needNewSess) { 1021 // create jpeg encoding session 1022 mm_jpeg_encode_params_t encodeParam; 1023 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t)); 1024 getJpegEncodingConfig(encodeParam, main_stream, thumb_stream); 1025 ALOGD("[KPI Perf] %s : call jpeg create_session", __func__); 1026 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId); 1027 if (ret != NO_ERROR) { 1028 ALOGE("%s: error creating a new jpeg encoding session", __func__); 1029 return ret; 1030 } 1031 needNewSess = FALSE; 1032 } 1033 1034 // Fill in new job 1035 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t)); 1036 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE; 1037 jpg_job.encode_job.session_id = mJpegSessionId; 1038 jpg_job.encode_job.src_index = main_frame->buf_idx; 1039 jpg_job.encode_job.dst_index = 0; 1040 1041 cam_rect_t crop; 1042 memset(&crop, 0, sizeof(cam_rect_t)); 1043 main_stream->getCropInfo(crop); 1044 1045 cam_dimension_t src_dim; 1046 memset(&src_dim, 0, sizeof(cam_dimension_t)); 1047 main_stream->getFrameDimension(src_dim); 1048 1049 // main dim 1050 jpg_job.encode_job.main_dim.src_dim = src_dim; 1051 jpg_job.encode_job.main_dim.dst_dim = src_dim; 1052 jpg_job.encode_job.main_dim.crop = crop; 1053 1054 // thumbnail dim 1055 if (m_bThumbnailNeeded == TRUE) { 1056 if (thumb_stream == NULL) { 1057 // need jpeg thumbnail, but no postview/preview stream exists 1058 // we use the main stream/frame to encode thumbnail 1059 thumb_stream = main_stream; 1060 thumb_frame = main_frame; 1061 } 1062 memset(&crop, 0, sizeof(cam_rect_t)); 1063 thumb_stream->getCropInfo(crop); 1064 memset(&src_dim, 0, sizeof(cam_dimension_t)); 1065 thumb_stream->getFrameDimension(src_dim); 1066 jpg_job.encode_job.thumb_dim.src_dim = src_dim; 1067 m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim); 1068 int rotation = m_parent->getJpegRotation(); 1069 if (rotation == 90 || rotation ==270) { 1070 // swap dimension if rotation is 90 or 270 1071 int32_t temp = jpg_job.encode_job.thumb_dim.dst_dim.height; 1072 jpg_job.encode_job.thumb_dim.dst_dim.height = 1073 jpg_job.encode_job.thumb_dim.dst_dim.width; 1074 jpg_job.encode_job.thumb_dim.dst_dim.width = temp; 1075 } 1076 jpg_job.encode_job.thumb_dim.crop = crop; 1077 jpg_job.encode_job.thumb_index = thumb_frame->buf_idx; 1078 } 1079 1080 // set rotation only when no online rotation or offline pp rotation is done before 1081 if (!m_parent->needRotationReprocess()) { 1082 jpg_job.encode_job.rotation = m_parent->getJpegRotation(); 1083 } 1084 ALOGV("%s: jpeg rotation is set to %d", __func__, jpg_job.encode_job.rotation); 1085 1086 // find meta data frame 1087 mm_camera_buf_def_t *meta_frame = NULL; 1088 for (int i = 0; i < jpeg_job_data->src_frame->num_bufs; i++) { 1089 // look through input superbuf 1090 if (jpeg_job_data->src_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 1091 meta_frame = jpeg_job_data->src_frame->bufs[i]; 1092 break; 1093 } 1094 } 1095 if (meta_frame == NULL && jpeg_job_data->src_reproc_frame != NULL) { 1096 // look through reprocess source superbuf 1097 for (int i = 0; i < jpeg_job_data->src_reproc_frame->num_bufs; i++) { 1098 if (jpeg_job_data->src_reproc_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 1099 meta_frame = jpeg_job_data->src_reproc_frame->bufs[i]; 1100 break; 1101 } 1102 } 1103 } 1104 if (meta_frame != NULL) { 1105 // fill in meta data frame ptr 1106 jpg_job.encode_job.p_metadata = (cam_metadata_info_t *)meta_frame->buffer; 1107 } 1108 1109 ALOGD("[KPI Perf] %s : call jpeg start_job", __func__); 1110 ret = mJpegHandle.start_job(&jpg_job, &jobId); 1111 if (ret == NO_ERROR) { 1112 // remember job info 1113 jpeg_job_data->jobId = jobId; 1114 } 1115 1116 return ret; 1117} 1118 1119/*=========================================================================== 1120 * FUNCTION : processRawImageImpl 1121 * 1122 * DESCRIPTION: function to send raw image to upper layer 1123 * 1124 * PARAMETERS : 1125 * @recvd_frame : frame to be encoded 1126 * 1127 * RETURN : int32_t type of status 1128 * NO_ERROR -- success 1129 * none-zero failure code 1130 *==========================================================================*/ 1131int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_frame) 1132{ 1133 int32_t rc = NO_ERROR; 1134 1135 mm_camera_buf_def_t *frame = NULL; 1136 for ( int i= 0 ; i < recvd_frame->num_bufs ; i++ ) { 1137 if ( recvd_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_SNAPSHOT || 1138 recvd_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_RAW ) { 1139 frame = recvd_frame->bufs[i]; 1140 break; 1141 } 1142 } 1143 if ( NULL == frame ) { 1144 ALOGE("%s: No valid raw buffer", __func__); 1145 return BAD_VALUE; 1146 } 1147 1148 QCameraMemory *rawMemObj = (QCameraMemory *)frame->mem_info; 1149 camera_memory_t *raw_mem = NULL; 1150 1151 if (rawMemObj != NULL) { 1152 raw_mem = rawMemObj->getMemory(frame->buf_idx, false); 1153 } 1154 1155 if (NULL != rawMemObj && NULL != raw_mem) { 1156 // dump frame into file 1157 m_parent->dumpFrameToFile(frame->buffer, frame->frame_len, 1158 frame->frame_idx, QCAMERA_DUMP_FRM_RAW); 1159 1160 // send data callback / notify for RAW_IMAGE 1161 if (NULL != m_parent->mDataCb && 1162 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) { 1163 qcamera_callback_argm_t cbArg; 1164 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 1165 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 1166 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE; 1167 cbArg.data = raw_mem; 1168 cbArg.index = 0; 1169 m_parent->m_cbNotifier.notifyCallback(cbArg); 1170 } 1171 if (NULL != m_parent->mNotifyCb && 1172 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) { 1173 qcamera_callback_argm_t cbArg; 1174 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 1175 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; 1176 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY; 1177 cbArg.ext1 = 0; 1178 cbArg.ext2 = 0; 1179 m_parent->m_cbNotifier.notifyCallback(cbArg); 1180 } 1181 1182 if ((m_parent->mDataCb != NULL) && 1183 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) > 0) { 1184 qcamera_release_data_t release_data; 1185 memset(&release_data, 0, sizeof(qcamera_release_data_t)); 1186 release_data.frame = recvd_frame; 1187 sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE, 1188 raw_mem, 1189 0, 1190 NULL, 1191 &release_data); 1192 } 1193 } else { 1194 ALOGE("%s: Cannot get raw mem", __func__); 1195 rc = UNKNOWN_ERROR; 1196 } 1197 1198 return rc; 1199} 1200 1201/*=========================================================================== 1202 * FUNCTION : dataProcessRoutine 1203 * 1204 * DESCRIPTION: data process routine that handles input data either from input 1205 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do 1206 * reprocess. 1207 * 1208 * PARAMETERS : 1209 * @data : user data ptr (QCameraPostProcessor) 1210 * 1211 * RETURN : None 1212 *==========================================================================*/ 1213void *QCameraPostProcessor::dataProcessRoutine(void *data) 1214{ 1215 int running = 1; 1216 int ret; 1217 uint8_t is_active = FALSE; 1218 uint8_t needNewSess = TRUE; 1219 QCameraPostProcessor *pme = (QCameraPostProcessor *)data; 1220 QCameraCmdThread *cmdThread = &pme->m_dataProcTh; 1221 1222 ALOGD("%s: E", __func__); 1223 do { 1224 do { 1225 ret = cam_sem_wait(&cmdThread->cmd_sem); 1226 if (ret != 0 && errno != EINVAL) { 1227 ALOGE("%s: cam_sem_wait error (%s)", 1228 __func__, strerror(errno)); 1229 return NULL; 1230 } 1231 } while (ret != 0); 1232 1233 // we got notified about new cmd avail in cmd queue 1234 camera_cmd_type_t cmd = cmdThread->getCmd(); 1235 switch (cmd) { 1236 case CAMERA_CMD_TYPE_START_DATA_PROC: 1237 ALOGD("%s: start data proc", __func__); 1238 is_active = TRUE; 1239 needNewSess = TRUE; 1240 break; 1241 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 1242 { 1243 ALOGD("%s: stop data proc", __func__); 1244 is_active = FALSE; 1245 1246 // cancel all ongoing jpeg jobs 1247 qcamera_jpeg_data_t *jpeg_job = 1248 (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1249 while (jpeg_job != NULL) { 1250 pme->mJpegHandle.abort_job(jpeg_job->jobId); 1251 1252 pme->releaseJpegJobData(jpeg_job); 1253 free(jpeg_job); 1254 1255 jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 1256 } 1257 1258 // destroy jpeg encoding session 1259 if ( 0 < pme->mJpegSessionId ) { 1260 pme->mJpegHandle.destroy_session(pme->mJpegSessionId); 1261 pme->mJpegSessionId = 0; 1262 } 1263 1264 // free jpeg out buf and exif obj 1265 if (pme->m_pJpegOutputMem != NULL) { 1266 pme->m_pJpegOutputMem->deallocate(); 1267 delete pme->m_pJpegOutputMem; 1268 pme->m_pJpegOutputMem = NULL; 1269 } 1270 if (pme->m_pJpegExifObj != NULL) { 1271 delete pme->m_pJpegExifObj; 1272 pme->m_pJpegExifObj = NULL; 1273 } 1274 needNewSess = TRUE; 1275 1276 // stop reproc channel if exists 1277 if (pme->m_pReprocChannel != NULL) { 1278 pme->m_pReprocChannel->stop(); 1279 delete pme->m_pReprocChannel; 1280 pme->m_pReprocChannel = NULL; 1281 } 1282 1283 // flush ongoing postproc Queue 1284 pme->m_ongoingPPQ.flush(); 1285 1286 // flush input jpeg Queue 1287 pme->m_inputJpegQ.flush(); 1288 1289 // flush input Postproc Queue 1290 pme->m_inputPPQ.flush(); 1291 1292 // flush input raw Queue 1293 pme->m_inputRawQ.flush(); 1294 1295 // signal cmd is completed 1296 cam_sem_post(&cmdThread->sync_sem); 1297 } 1298 break; 1299 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 1300 { 1301 ALOGD("%s: Do next job, active is %d", __func__, is_active); 1302 if (is_active == TRUE) { 1303 // check if there is any ongoing jpeg jobs 1304 if (pme->m_ongoingJpegQ.isEmpty()) { 1305 // no ongoing jpeg job, we are fine to send jpeg encoding job 1306 qcamera_jpeg_data_t *jpeg_job = 1307 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 1308 1309 if (NULL != jpeg_job) { 1310 //play shutter sound 1311 pme->m_parent->playShutter(); 1312 1313 // add into ongoing jpeg job Q 1314 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job); 1315 ret = pme->encodeData(jpeg_job, needNewSess); 1316 if (NO_ERROR != ret) { 1317 // dequeue the last one 1318 pme->m_ongoingJpegQ.dequeue(false); 1319 1320 pme->releaseJpegJobData(jpeg_job); 1321 free(jpeg_job); 1322 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 1323 } 1324 } 1325 } 1326 1327 // process raw data if any 1328 mm_camera_super_buf_t *super_buf = 1329 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 1330 1331 if (NULL != super_buf) { 1332 //play shutter sound 1333 pme->m_parent->playShutter(); 1334 ret = pme->processRawImageImpl(super_buf); 1335 if (NO_ERROR != ret) { 1336 pme->releaseSuperBuf(super_buf); 1337 free(super_buf); 1338 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 1339 } 1340 } 1341 1342 mm_camera_super_buf_t *pp_frame = 1343 (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 1344 if (NULL != pp_frame) { 1345 qcamera_pp_data_t *pp_job = 1346 (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t)); 1347 if (pp_job != NULL) { 1348 memset(pp_job, 0, sizeof(qcamera_pp_data_t)); 1349 if (pme->m_pReprocChannel != NULL) { 1350 // add into ongoing PP job Q 1351 pp_job->src_frame = pp_frame; 1352 pme->m_ongoingPPQ.enqueue((void *)pp_job); 1353 ret = pme->m_pReprocChannel->doReprocess(pp_frame); 1354 if (NO_ERROR != ret) { 1355 // remove from ongoing PP job Q 1356 pme->m_ongoingPPQ.dequeue(false); 1357 } 1358 } else { 1359 ALOGE("%s: Reprocess channel is NULL", __func__); 1360 ret = -1; 1361 } 1362 } else { 1363 ALOGE("%s: no mem for qcamera_pp_data_t", __func__); 1364 ret = -1; 1365 } 1366 1367 if (0 != ret) { 1368 // free pp_job 1369 if (pp_job != NULL) { 1370 free(pp_job); 1371 } 1372 // free frame 1373 if (pp_frame != NULL) { 1374 pme->releaseSuperBuf(pp_frame); 1375 free(pp_frame); 1376 } 1377 // send error notify 1378 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); 1379 } 1380 } 1381 } else { 1382 // not active, simply return buf and do no op 1383 qcamera_jpeg_data_t *jpeg_data = 1384 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 1385 if (NULL != jpeg_data) { 1386 pme->releaseJpegJobData(jpeg_data); 1387 free(jpeg_data); 1388 } 1389 mm_camera_super_buf_t *super_buf = 1390 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 1391 if (NULL != super_buf) { 1392 pme->releaseSuperBuf(super_buf); 1393 free(super_buf); 1394 } 1395 super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 1396 if (NULL != super_buf) { 1397 pme->releaseSuperBuf(super_buf); 1398 free(super_buf); 1399 } 1400 } 1401 } 1402 break; 1403 case CAMERA_CMD_TYPE_EXIT: 1404 running = 0; 1405 break; 1406 default: 1407 break; 1408 } 1409 } while (running); 1410 ALOGD("%s: X", __func__); 1411 return NULL; 1412} 1413 1414/*=========================================================================== 1415 * FUNCTION : getJpegPaddingReq 1416 * 1417 * DESCRIPTION: function to add an entry to exif data 1418 * 1419 * PARAMETERS : 1420 * @padding_info : jpeg specific padding requirement 1421 * 1422 * RETURN : int32_t type of status 1423 * NO_ERROR -- success 1424 * none-zero failure code 1425 *==========================================================================*/ 1426int32_t QCameraPostProcessor::getJpegPaddingReq(cam_padding_info_t &padding_info) 1427{ 1428 // TODO: hardcode for now, needs to query from mm-jpeg-interface 1429 padding_info.width_padding = CAM_PAD_NONE; 1430 padding_info.height_padding = CAM_PAD_TO_16; 1431 padding_info.plane_padding = CAM_PAD_TO_WORD; 1432 return NO_ERROR; 1433} 1434 1435/*=========================================================================== 1436 * FUNCTION : QCameraExif 1437 * 1438 * DESCRIPTION: constructor of QCameraExif 1439 * 1440 * PARAMETERS : None 1441 * 1442 * RETURN : None 1443 *==========================================================================*/ 1444QCameraExif::QCameraExif() 1445 : m_nNumEntries(0) 1446{ 1447 memset(m_Entries, 0, sizeof(m_Entries)); 1448} 1449 1450/*=========================================================================== 1451 * FUNCTION : ~QCameraExif 1452 * 1453 * DESCRIPTION: deconstructor of QCameraExif. Will release internal memory ptr. 1454 * 1455 * PARAMETERS : None 1456 * 1457 * RETURN : None 1458 *==========================================================================*/ 1459QCameraExif::~QCameraExif() 1460{ 1461 for (uint32_t i = 0; i < m_nNumEntries; i++) { 1462 switch (m_Entries[i].tag_entry.type) { 1463 case EXIF_BYTE: 1464 { 1465 if (m_Entries[i].tag_entry.count > 1 && 1466 m_Entries[i].tag_entry.data._bytes != NULL) { 1467 free(m_Entries[i].tag_entry.data._bytes); 1468 m_Entries[i].tag_entry.data._bytes = NULL; 1469 } 1470 } 1471 break; 1472 case EXIF_ASCII: 1473 { 1474 if (m_Entries[i].tag_entry.data._ascii != NULL) { 1475 free(m_Entries[i].tag_entry.data._ascii); 1476 m_Entries[i].tag_entry.data._ascii = NULL; 1477 } 1478 } 1479 break; 1480 case EXIF_SHORT: 1481 { 1482 if (m_Entries[i].tag_entry.count > 1 && 1483 m_Entries[i].tag_entry.data._shorts != NULL) { 1484 free(m_Entries[i].tag_entry.data._shorts); 1485 m_Entries[i].tag_entry.data._shorts = NULL; 1486 } 1487 } 1488 break; 1489 case EXIF_LONG: 1490 { 1491 if (m_Entries[i].tag_entry.count > 1 && 1492 m_Entries[i].tag_entry.data._longs != NULL) { 1493 free(m_Entries[i].tag_entry.data._longs); 1494 m_Entries[i].tag_entry.data._longs = NULL; 1495 } 1496 } 1497 break; 1498 case EXIF_RATIONAL: 1499 { 1500 if (m_Entries[i].tag_entry.count > 1 && 1501 m_Entries[i].tag_entry.data._rats != NULL) { 1502 free(m_Entries[i].tag_entry.data._rats); 1503 m_Entries[i].tag_entry.data._rats = NULL; 1504 } 1505 } 1506 break; 1507 case EXIF_UNDEFINED: 1508 { 1509 if (m_Entries[i].tag_entry.data._undefined != NULL) { 1510 free(m_Entries[i].tag_entry.data._undefined); 1511 m_Entries[i].tag_entry.data._undefined = NULL; 1512 } 1513 } 1514 break; 1515 case EXIF_SLONG: 1516 { 1517 if (m_Entries[i].tag_entry.count > 1 && 1518 m_Entries[i].tag_entry.data._slongs != NULL) { 1519 free(m_Entries[i].tag_entry.data._slongs); 1520 m_Entries[i].tag_entry.data._slongs = NULL; 1521 } 1522 } 1523 break; 1524 case EXIF_SRATIONAL: 1525 { 1526 if (m_Entries[i].tag_entry.count > 1 && 1527 m_Entries[i].tag_entry.data._srats != NULL) { 1528 free(m_Entries[i].tag_entry.data._srats); 1529 m_Entries[i].tag_entry.data._srats = NULL; 1530 } 1531 } 1532 break; 1533 } 1534 } 1535} 1536 1537/*=========================================================================== 1538 * FUNCTION : addEntry 1539 * 1540 * DESCRIPTION: function to add an entry to exif data 1541 * 1542 * PARAMETERS : 1543 * @tagid : exif tag ID 1544 * @type : data type 1545 * @count : number of data in uint of its type 1546 * @data : input data ptr 1547 * 1548 * RETURN : int32_t type of status 1549 * NO_ERROR -- success 1550 * none-zero failure code 1551 *==========================================================================*/ 1552int32_t QCameraExif::addEntry(exif_tag_id_t tagid, 1553 exif_tag_type_t type, 1554 uint32_t count, 1555 void *data) 1556{ 1557 int32_t rc = NO_ERROR; 1558 if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) { 1559 ALOGE("%s: Number of entries exceeded limit", __func__); 1560 return NO_MEMORY; 1561 } 1562 1563 m_Entries[m_nNumEntries].tag_id = tagid; 1564 m_Entries[m_nNumEntries].tag_entry.type = type; 1565 m_Entries[m_nNumEntries].tag_entry.count = count; 1566 m_Entries[m_nNumEntries].tag_entry.copy = 1; 1567 switch (type) { 1568 case EXIF_BYTE: 1569 { 1570 if (count > 1) { 1571 uint8_t *values = (uint8_t *)malloc(count); 1572 if (values == NULL) { 1573 ALOGE("%s: No memory for byte array", __func__); 1574 rc = NO_MEMORY; 1575 } else { 1576 memcpy(values, data, count); 1577 m_Entries[m_nNumEntries].tag_entry.data._bytes = values; 1578 } 1579 } else { 1580 m_Entries[m_nNumEntries].tag_entry.data._byte = *(uint8_t *)data; 1581 } 1582 } 1583 break; 1584 case EXIF_ASCII: 1585 { 1586 char *str = NULL; 1587 str = (char *)malloc(count + 1); 1588 if (str == NULL) { 1589 ALOGE("%s: No memory for ascii string", __func__); 1590 rc = NO_MEMORY; 1591 } else { 1592 memset(str, 0, count + 1); 1593 memcpy(str, data, count); 1594 m_Entries[m_nNumEntries].tag_entry.data._ascii = str; 1595 } 1596 } 1597 break; 1598 case EXIF_SHORT: 1599 { 1600 if (count > 1) { 1601 uint16_t *values = (uint16_t *)malloc(count * sizeof(uint16_t)); 1602 if (values == NULL) { 1603 ALOGE("%s: No memory for short array", __func__); 1604 rc = NO_MEMORY; 1605 } else { 1606 memcpy(values, data, count * sizeof(uint16_t)); 1607 m_Entries[m_nNumEntries].tag_entry.data._shorts = values; 1608 } 1609 } else { 1610 m_Entries[m_nNumEntries].tag_entry.data._short = *(uint16_t *)data; 1611 } 1612 } 1613 break; 1614 case EXIF_LONG: 1615 { 1616 if (count > 1) { 1617 uint32_t *values = (uint32_t *)malloc(count * sizeof(uint32_t)); 1618 if (values == NULL) { 1619 ALOGE("%s: No memory for long array", __func__); 1620 rc = NO_MEMORY; 1621 } else { 1622 memcpy(values, data, count * sizeof(uint32_t)); 1623 m_Entries[m_nNumEntries].tag_entry.data._longs = values; 1624 } 1625 } else { 1626 m_Entries[m_nNumEntries].tag_entry.data._long = *(uint32_t *)data; 1627 } 1628 } 1629 break; 1630 case EXIF_RATIONAL: 1631 { 1632 if (count > 1) { 1633 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t)); 1634 if (values == NULL) { 1635 ALOGE("%s: No memory for rational array", __func__); 1636 rc = NO_MEMORY; 1637 } else { 1638 memcpy(values, data, count * sizeof(rat_t)); 1639 m_Entries[m_nNumEntries].tag_entry.data._rats = values; 1640 } 1641 } else { 1642 m_Entries[m_nNumEntries].tag_entry.data._rat = *(rat_t *)data; 1643 } 1644 } 1645 break; 1646 case EXIF_UNDEFINED: 1647 { 1648 uint8_t *values = (uint8_t *)malloc(count); 1649 if (values == NULL) { 1650 ALOGE("%s: No memory for undefined array", __func__); 1651 rc = NO_MEMORY; 1652 } else { 1653 memcpy(values, data, count); 1654 m_Entries[m_nNumEntries].tag_entry.data._undefined = values; 1655 } 1656 } 1657 break; 1658 case EXIF_SLONG: 1659 { 1660 if (count > 1) { 1661 int32_t *values = (int32_t *)malloc(count * sizeof(int32_t)); 1662 if (values == NULL) { 1663 ALOGE("%s: No memory for signed long array", __func__); 1664 rc = NO_MEMORY; 1665 } else { 1666 memcpy(values, data, count * sizeof(int32_t)); 1667 m_Entries[m_nNumEntries].tag_entry.data._slongs = values; 1668 } 1669 } else { 1670 m_Entries[m_nNumEntries].tag_entry.data._slong = *(int32_t *)data; 1671 } 1672 } 1673 break; 1674 case EXIF_SRATIONAL: 1675 { 1676 if (count > 1) { 1677 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t)); 1678 if (values == NULL) { 1679 ALOGE("%s: No memory for signed rational array", __func__); 1680 rc = NO_MEMORY; 1681 } else { 1682 memcpy(values, data, count * sizeof(srat_t)); 1683 m_Entries[m_nNumEntries].tag_entry.data._srats = values; 1684 } 1685 } else { 1686 m_Entries[m_nNumEntries].tag_entry.data._srat = *(srat_t *)data; 1687 } 1688 } 1689 break; 1690 } 1691 1692 // Increase number of entries 1693 m_nNumEntries++; 1694 return rc; 1695} 1696 1697}; // namespace qcamera 1698