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