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