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