QCamera3PostProc.cpp revision f2fc1625456303cb52ec068d25308229e4322d4c
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 "QCamera3PostProc" 31 32#include <stdlib.h> 33#include <utils/Errors.h> 34 35#include "QCamera3PostProc.h" 36#include "QCamera3HWI.h" 37#include "QCamera3Channel.h" 38#include "QCamera3Stream.h" 39 40namespace qcamera { 41 42/*=========================================================================== 43 * FUNCTION : QCamera3PostProcessor 44 * 45 * DESCRIPTION: constructor of QCamera3PostProcessor. 46 * 47 * PARAMETERS : 48 * @cam_ctrl : ptr to HWI object 49 * 50 * RETURN : None 51 *==========================================================================*/ 52QCamera3PostProcessor::QCamera3PostProcessor(QCamera3PicChannel* ch_ctrl) 53 : m_parent(ch_ctrl), 54 mJpegCB(NULL), 55 mJpegUserData(NULL), 56 mJpegClientHandle(0), 57 mJpegSessionId(0), 58 m_pJpegExifObj(NULL), 59 m_bThumbnailNeeded(TRUE), 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 : ~QCamera3PostProcessor 71 * 72 * DESCRIPTION: deconstructor of QCamera3PostProcessor. 73 * 74 * PARAMETERS : None 75 * 76 * RETURN : None 77 *==========================================================================*/ 78QCamera3PostProcessor::~QCamera3PostProcessor() 79{ 80 if (m_pJpegExifObj != NULL) { 81 delete m_pJpegExifObj; 82 m_pJpegExifObj = NULL; 83 } 84} 85 86/*=========================================================================== 87 * FUNCTION : init 88 * 89 * DESCRIPTION: initialization of postprocessor 90 * 91 * PARAMETERS : 92 * @jpeg_cb : callback to handle jpeg event from mm-camera-interface 93 * @user_data : user data ptr for jpeg callback 94 * 95 * RETURN : int32_t type of status 96 * NO_ERROR -- success 97 * none-zero failure code 98 *==========================================================================*/ 99int32_t QCamera3PostProcessor::init(jpeg_encode_callback_t jpeg_cb, void *user_data) 100{ 101 mJpegCB = jpeg_cb; 102 mJpegUserData = user_data; 103 104 mJpegClientHandle = jpeg_open(&mJpegHandle); 105 if(!mJpegClientHandle) { 106 ALOGE("%s : jpeg_open did not work", __func__); 107 return UNKNOWN_ERROR; 108 } 109 110 m_dataProcTh.launch(dataProcessRoutine, this); 111 112 return NO_ERROR; 113} 114 115/*=========================================================================== 116 * FUNCTION : deinit 117 * 118 * DESCRIPTION: de-initialization of postprocessor 119 * 120 * PARAMETERS : None 121 * 122 * RETURN : int32_t type of status 123 * NO_ERROR -- success 124 * none-zero failure code 125 *==========================================================================*/ 126int32_t QCamera3PostProcessor::deinit() 127{ 128 m_dataProcTh.exit(); 129 130 if(mJpegClientHandle > 0) { 131 int rc = mJpegHandle.close(mJpegClientHandle); 132 ALOGE("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x", 133 __func__, rc, mJpegClientHandle); 134 mJpegClientHandle = 0; 135 memset(&mJpegHandle, 0, sizeof(mJpegHandle)); 136 } 137 138 return NO_ERROR; 139} 140 141/*=========================================================================== 142 * FUNCTION : start 143 * 144 * DESCRIPTION: start postprocessor. Data process thread and data notify thread 145 * will be launched. 146 * 147 * PARAMETERS : 148 * @pSrcChannel : source channel obj ptr that possibly needs reprocess 149 * 150 * RETURN : int32_t type of status 151 * NO_ERROR -- success 152 * none-zero failure code 153 * 154 * NOTE : if any reprocess is needed, a reprocess channel/stream 155 * will be started. 156 *==========================================================================*/ 157int32_t QCamera3PostProcessor::start(QCamera3Memory* mMemory) 158{ 159 int32_t rc = NO_ERROR; 160 mJpegMem = mMemory; 161 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE); 162 163 return rc; 164} 165 166/*=========================================================================== 167 * FUNCTION : stop 168 * 169 * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped. 170 * 171 * PARAMETERS : None 172 * 173 * RETURN : int32_t type of status 174 * NO_ERROR -- success 175 * none-zero failure code 176 * 177 * NOTE : reprocess channel will be stopped and deleted if there is any 178 *==========================================================================*/ 179int32_t QCamera3PostProcessor::stop() 180{ 181 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE); 182 183 return NO_ERROR; 184} 185 186/*=========================================================================== 187 * FUNCTION : getJpegEncodingConfig 188 * 189 * DESCRIPTION: function to prepare encoding job information 190 * 191 * PARAMETERS : 192 * @encode_parm : param to be filled with encoding configuration 193 * 194 * RETURN : int32_t type of status 195 * NO_ERROR -- success 196 * none-zero failure code 197 *==========================================================================*/ 198int32_t QCamera3PostProcessor::getJpegEncodingConfig(mm_jpeg_encode_params_t& encode_parm, 199 QCamera3Stream *main_stream, 200 QCamera3Stream *thumb_stream) 201{ 202 ALOGV("%s : E", __func__); 203 int32_t ret = NO_ERROR; 204 205 encode_parm.jpeg_cb = mJpegCB; 206 encode_parm.userdata = mJpegUserData; 207 208 m_bThumbnailNeeded = TRUE; // need encode thumbnail by default 209 cam_dimension_t thumbnailSize; 210 memset(&thumbnailSize, 0, sizeof(cam_dimension_t)); 211 m_parent->getThumbnailSize(thumbnailSize); 212 if (thumbnailSize.width == 0 && thumbnailSize.height == 0) { 213 // (0,0) means no thumbnail 214 m_bThumbnailNeeded = FALSE; 215 } 216 encode_parm.encode_thumbnail = m_bThumbnailNeeded; 217 218 // get color format 219 cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12; //default value 220 main_stream->getFormat(img_fmt); 221 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt); 222 223 // get jpeg quality 224 encode_parm.quality = m_parent->getJpegQuality(); 225 if (encode_parm.quality <= 0) { 226 encode_parm.quality = 85; 227 } 228 229 // get exif data 230 if (m_pJpegExifObj != NULL) { 231 delete m_pJpegExifObj; 232 m_pJpegExifObj = NULL; 233 } 234 m_pJpegExifObj = m_parent->getExifData(); 235 if (m_pJpegExifObj != NULL) { 236 encode_parm.exif_info.exif_data = m_pJpegExifObj->getEntries(); 237 encode_parm.exif_info.numOfEntries = m_pJpegExifObj->getNumOfEntries(); 238 } 239 240 cam_frame_len_offset_t main_offset; 241 memset(&main_offset, 0, sizeof(cam_frame_len_offset_t)); 242 main_stream->getFrameOffset(main_offset); 243 244 // src buf config 245 //Pass input main image buffer info to encoder. 246 QCamera3Memory *pStreamMem = main_stream->getStreamBufs(); 247 if (pStreamMem == NULL) { 248 ALOGE("%s: cannot get stream bufs from main stream", __func__); 249 ret = BAD_VALUE; 250 goto on_error; 251 } 252 encode_parm.num_src_bufs = pStreamMem->getCnt(); 253 for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) { 254 if (pStreamMem != NULL) { 255 encode_parm.src_main_buf[i].index = i; 256 encode_parm.src_main_buf[i].buf_size = pStreamMem->getSize(i); 257 encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i); 258 encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i); 259 encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV; 260 encode_parm.src_main_buf[i].offset = main_offset; 261 } 262 } 263 264 //Pass input thumbnail buffer info to encoder. 265 //Note: In this version thumb_stream = main_stream 266 if (m_bThumbnailNeeded == TRUE) { 267 if (thumb_stream == NULL) { 268 thumb_stream = main_stream; 269 } 270 pStreamMem = thumb_stream->getStreamBufs(); 271 if (pStreamMem == NULL) { 272 ALOGE("%s: cannot get stream bufs from thumb stream", __func__); 273 ret = BAD_VALUE; 274 goto on_error; 275 } 276 cam_frame_len_offset_t thumb_offset; 277 memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t)); 278 thumb_stream->getFrameOffset(thumb_offset); 279 encode_parm.num_tmb_bufs = pStreamMem->getCnt(); 280 for (int i = 0; i < pStreamMem->getCnt(); i++) { 281 if (pStreamMem != NULL) { 282 encode_parm.src_thumb_buf[i].index = i; 283 encode_parm.src_thumb_buf[i].buf_size = pStreamMem->getSize(i); 284 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i); 285 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i); 286 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV; 287 encode_parm.src_thumb_buf[i].offset = thumb_offset; 288 } 289 } 290 } 291 292 //Pass output jpeg buffer info to encoder. 293 //mJpegMem is allocated by framework. 294 encode_parm.num_dst_bufs = 1; 295 encode_parm.dest_buf[0].index = 0; 296 encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(0); 297 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(0); 298 encode_parm.dest_buf[0].fd = mJpegMem->getFd(0); 299 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV; 300 encode_parm.dest_buf[0].offset = main_offset; 301 302 ALOGV("%s : X", __func__); 303 return NO_ERROR; 304 305on_error: 306 if (m_pJpegExifObj != NULL) { 307 delete m_pJpegExifObj; 308 m_pJpegExifObj = NULL; 309 } 310 ALOGV("%s : X with error %d", __func__, ret); 311 return ret; 312} 313 314/*=========================================================================== 315 * FUNCTION : processData 316 * 317 * DESCRIPTION: enqueue data into dataProc thread 318 * 319 * PARAMETERS : 320 * @frame : process frame received from mm-camera-interface 321 * 322 * RETURN : int32_t type of status 323 * NO_ERROR -- success 324 * none-zero failure code 325 * 326 * NOTE : depends on if offline reprocess is needed, received frame will 327 * be sent to either input queue of postprocess or jpeg encoding 328 *==========================================================================*/ 329int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame) 330{ 331 ALOGD("%s: no need offline reprocess, sending to jpeg encoding", __func__); 332 qcamera_jpeg_data_t *jpeg_job = 333 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t)); 334 if (jpeg_job == NULL) { 335 ALOGE("%s: No memory for jpeg job", __func__); 336 return NO_MEMORY; 337 } 338 339 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t)); 340 jpeg_job->src_frame = frame; 341 342 // enqueu to jpeg input queue 343 m_inputJpegQ.enqueue((void *)jpeg_job); 344 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 345 346 return NO_ERROR; 347} 348 349/*=========================================================================== 350 * FUNCTION : processRawData 351 * 352 * DESCRIPTION: enqueue raw data into dataProc thread 353 * 354 * PARAMETERS : 355 * @frame : process frame received from mm-camera-interface 356 * 357 * RETURN : int32_t type of status 358 * NO_ERROR -- success 359 * none-zero failure code 360 *==========================================================================*/ 361int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame) 362{ 363 // enqueu to raw input queue 364 m_inputRawQ.enqueue((void *)frame); 365 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 366 return NO_ERROR; 367} 368 369/*=========================================================================== 370 * FUNCTION : processPPData 371 * 372 * DESCRIPTION: process received frame after reprocess. 373 * 374 * PARAMETERS : 375 * @frame : received frame from reprocess channel. 376 * 377 * RETURN : int32_t type of status 378 * NO_ERROR -- success 379 * none-zero failure code 380 * 381 * NOTE : The frame after reprocess need to send to jpeg encoding. 382 *==========================================================================*/ 383int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame) 384{ 385 qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue(); 386 387 if (job == NULL || job->src_frame == NULL) { 388 ALOGE("%s: Cannot find reprocess job", __func__); 389 return BAD_VALUE; 390 } 391 392 qcamera_jpeg_data_t *jpeg_job = 393 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t)); 394 if (jpeg_job == NULL) { 395 ALOGE("%s: No memory for jpeg job", __func__); 396 return NO_MEMORY; 397 } 398 399 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t)); 400 jpeg_job->src_frame = frame; 401 jpeg_job->src_reproc_frame = job->src_frame; 402 403 // free pp job buf 404 free(job); 405 406 // enqueu reprocessed frame to jpeg input queue 407 m_inputJpegQ.enqueue((void *)jpeg_job); 408 409 // wait up data proc thread 410 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 411 412 return NO_ERROR; 413} 414 415/*=========================================================================== 416 * FUNCTION : findJpegJobByJobId 417 * 418 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID 419 * 420 * PARAMETERS : 421 * @jobId : job Id of the job 422 * 423 * RETURN : ptr to a jpeg job struct. NULL if not found. 424 * 425 * NOTE : Currently only one job is sending to mm-jpeg-interface for jpeg 426 * encoding. Therefore simply dequeue from the ongoing Jpeg Queue 427 * will serve the purpose to find the jpeg job. 428 *==========================================================================*/ 429qcamera_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId) 430{ 431 qcamera_jpeg_data_t * job = NULL; 432 if (jobId == 0) { 433 ALOGE("%s: not a valid jpeg jobId", __func__); 434 return NULL; 435 } 436 437 // currely only one jpeg job ongoing, so simply dequeue the head 438 job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue(); 439 return job; 440} 441 442/*=========================================================================== 443 * FUNCTION : releasePPInputData 444 * 445 * DESCRIPTION: callback function to release post process input data node 446 * 447 * PARAMETERS : 448 * @data : ptr to post process input data 449 * @user_data : user data ptr (QCamera3Reprocessor) 450 * 451 * RETURN : None 452 *==========================================================================*/ 453void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data) 454{ 455 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data; 456 if (NULL != pme) { 457 pme->releaseSuperBuf((mm_camera_super_buf_t *)data); 458 } 459} 460 461/*=========================================================================== 462 * FUNCTION : releaseJpegData 463 * 464 * DESCRIPTION: callback function to release jpeg job node 465 * 466 * PARAMETERS : 467 * @data : ptr to ongoing jpeg job data 468 * @user_data : user data ptr (QCamera3Reprocessor) 469 * 470 * RETURN : None 471 *==========================================================================*/ 472void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data) 473{ 474 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data; 475 if (NULL != pme) { 476 pme->releaseJpegJobData((qcamera_jpeg_data_t *)data); 477 } 478} 479 480/*=========================================================================== 481 * FUNCTION : releaseOngoingPPData 482 * 483 * DESCRIPTION: callback function to release ongoing postprocess job node 484 * 485 * PARAMETERS : 486 * @data : ptr to onging postprocess job 487 * @user_data : user data ptr (QCamera3Reprocessor) 488 * 489 * RETURN : None 490 *==========================================================================*/ 491void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data) 492{ 493 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data; 494 if (NULL != pme) { 495 qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data; 496 if (NULL != pp_job->src_frame) { 497 pme->releaseSuperBuf(pp_job->src_frame); 498 free(pp_job->src_frame); 499 pp_job->src_frame = NULL; 500 } 501 } 502} 503 504/*=========================================================================== 505 * FUNCTION : releaseSuperBuf 506 * 507 * DESCRIPTION: function to release a superbuf frame by returning back to kernel 508 * 509 * PARAMETERS : 510 * @super_buf : ptr to the superbuf frame 511 * 512 * RETURN : None 513 *==========================================================================*/ 514void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf) 515{ 516 if (NULL != super_buf) { 517 if (m_parent != NULL) { 518 m_parent->bufDone(super_buf); 519 } 520 } 521} 522 523/*=========================================================================== 524 * FUNCTION : releaseJpegJobData 525 * 526 * DESCRIPTION: function to release internal resources in jpeg job struct 527 * 528 * PARAMETERS : 529 * @job : ptr to jpeg job struct 530 * 531 * RETURN : None 532 * 533 * NOTE : original source frame need to be queued back to kernel for 534 * future use. Output buf of jpeg job need to be released since 535 * it's allocated for each job. Exif object need to be deleted. 536 *==========================================================================*/ 537void QCamera3PostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job) 538{ 539 ALOGV("%s: E", __func__); 540 if (NULL != job) { 541 if (NULL != job->src_reproc_frame) { 542 releaseSuperBuf(job->src_reproc_frame); 543 free(job->src_reproc_frame); 544 job->src_reproc_frame = NULL; 545 } 546 547 if (NULL != job->src_frame) { 548 releaseSuperBuf(job->src_frame); 549 free(job->src_frame); 550 job->src_frame = NULL; 551 } 552 mJpegMem = NULL; 553 } 554 ALOGV("%s: X", __func__); 555} 556 557/*=========================================================================== 558 * FUNCTION : getColorfmtFromImgFmt 559 * 560 * DESCRIPTION: function to return jpeg color format based on its image format 561 * 562 * PARAMETERS : 563 * @img_fmt : image format 564 * 565 * RETURN : jpeg color format that can be understandable by omx lib 566 *==========================================================================*/ 567mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt) 568{ 569 switch (img_fmt) { 570 case CAM_FORMAT_YUV_420_NV21: 571 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 572 case CAM_FORMAT_YUV_420_NV21_ADRENO: 573 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 574 case CAM_FORMAT_YUV_420_NV12: 575 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 576 case CAM_FORMAT_YUV_420_YV12: 577 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2; 578 case CAM_FORMAT_YUV_422_NV61: 579 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1; 580 case CAM_FORMAT_YUV_422_NV16: 581 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1; 582 default: 583 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 584 } 585} 586 587/*=========================================================================== 588 * FUNCTION : getJpegImgTypeFromImgFmt 589 * 590 * DESCRIPTION: function to return jpeg encode image type based on its image format 591 * 592 * PARAMETERS : 593 * @img_fmt : image format 594 * 595 * RETURN : return jpeg source image format (YUV or Bitstream) 596 *==========================================================================*/ 597mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt) 598{ 599 switch (img_fmt) { 600 case CAM_FORMAT_YUV_420_NV21: 601 case CAM_FORMAT_YUV_420_NV21_ADRENO: 602 case CAM_FORMAT_YUV_420_NV12: 603 case CAM_FORMAT_YUV_420_YV12: 604 case CAM_FORMAT_YUV_422_NV61: 605 case CAM_FORMAT_YUV_422_NV16: 606 return MM_JPEG_FMT_YUV; 607 default: 608 return MM_JPEG_FMT_YUV; 609 } 610} 611 612/*=========================================================================== 613 * FUNCTION : encodeData 614 * 615 * DESCRIPTION: function to prepare encoding job information and send to 616 * mm-jpeg-interface to do the encoding job 617 * 618 * PARAMETERS : 619 * @jpeg_job_data : ptr to a struct saving job related information 620 * @needNewSess : flag to indicate if a new jpeg encoding session need 621 * to be created. After creation, this flag will be toggled 622 * 623 * RETURN : int32_t type of status 624 * NO_ERROR -- success 625 * none-zero failure code 626 *==========================================================================*/ 627int32_t QCamera3PostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data, 628 uint8_t &needNewSess) 629{ 630 ALOGV("%s : E", __func__); 631 int32_t ret = NO_ERROR; 632 mm_jpeg_job_t jpg_job; 633 uint32_t jobId = 0; 634 QCamera3Stream *main_stream = NULL; 635 mm_camera_buf_def_t *main_frame = NULL; 636 QCamera3Stream *thumb_stream = NULL; 637 mm_camera_buf_def_t *thumb_frame = NULL; 638 mm_camera_super_buf_t *recvd_frame = jpeg_job_data->src_frame; 639 640 // find channel 641 QCamera3Channel *pChannel = m_parent; 642 // check reprocess channel if not found 643 if (pChannel == NULL) { 644 ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here", 645 __func__, recvd_frame->ch_id); 646 return BAD_VALUE; 647 } 648 649 // find snapshot frame and thumnail frame 650 //Note: In this version we will receive only snapshot frame. 651 for (int i = 0; i < recvd_frame->num_bufs; i++) { 652 QCamera3Stream *pStream = 653 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id); 654 if (pStream != NULL) { 655 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) || 656 pStream->isTypeOf(CAM_STREAM_TYPE_OFFLINE_PROC)) { 657 main_stream = pStream; 658 main_frame = recvd_frame->bufs[i]; 659 } else if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) || 660 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW)) { 661 thumb_stream = pStream; 662 thumb_frame = recvd_frame->bufs[i]; 663 } 664 } 665 } 666 667 if(NULL == main_frame){ 668 ALOGE("%s : Main frame is NULL", __func__); 669 return BAD_VALUE; 670 } 671 672 QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info; 673 if (NULL == memObj) { 674 ALOGE("%s : Memeory Obj of main frame is NULL", __func__); 675 return NO_MEMORY; 676 } 677 678 // clean and invalidate cache ops through mem obj of the frame 679 memObj->cleanInvalidateCache(main_frame->buf_idx); 680 681 if (thumb_frame != NULL) { 682 QCamera3Memory *thumb_memObj = (QCamera3Memory *)thumb_frame->mem_info; 683 if (NULL != thumb_memObj) { 684 // clean and invalidate cache ops through mem obj of the frame 685 thumb_memObj->cleanInvalidateCache(thumb_frame->buf_idx); 686 } 687 } 688 689 if (mJpegClientHandle <= 0) { 690 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__); 691 return UNKNOWN_ERROR; 692 } 693 694 ALOGE("%s: Need new session?:%d",__func__, needNewSess); 695 if (needNewSess) { 696 // create jpeg encoding session 697 mm_jpeg_encode_params_t encodeParam; 698 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t)); 699 700 getJpegEncodingConfig(encodeParam, main_stream, thumb_stream); 701 ALOGE("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__, 702 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs); 703 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId); 704 if (ret != NO_ERROR) { 705 ALOGE("%s: error creating a new jpeg encoding session", __func__); 706 return ret; 707 } 708 needNewSess = FALSE; 709 } 710 711 // Fill in new job 712 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t)); 713 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE; 714 jpg_job.encode_job.session_id = mJpegSessionId; 715 jpg_job.encode_job.src_index = main_frame->buf_idx; 716 jpg_job.encode_job.dst_index = 0; 717 718 cam_rect_t crop; 719 memset(&crop, 0, sizeof(cam_rect_t)); 720 //TBD_later - Zoom event removed in stream 721 //main_stream->getCropInfo(crop); 722 723 cam_dimension_t src_dim; 724 memset(&src_dim, 0, sizeof(cam_dimension_t)); 725 main_stream->getFrameDimension(src_dim); 726 727 // main dim 728 jpg_job.encode_job.main_dim.src_dim = src_dim; 729 jpg_job.encode_job.main_dim.dst_dim = src_dim; 730 jpg_job.encode_job.main_dim.crop = crop; 731 732 // thumbnail dim 733 ALOGE("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded); 734 if (m_bThumbnailNeeded == TRUE) { 735 if (thumb_stream == NULL) { 736 // need jpeg thumbnail, but no postview/preview stream exists 737 // we use the main stream/frame to encode thumbnail 738 thumb_stream = main_stream; 739 thumb_frame = main_frame; 740 } 741 memset(&crop, 0, sizeof(cam_rect_t)); 742 //TBD_later - Zoom event removed in stream 743 //thumb_stream->getCropInfo(crop); 744 memset(&src_dim, 0, sizeof(cam_dimension_t)); 745 thumb_stream->getFrameDimension(src_dim); 746 jpg_job.encode_job.thumb_dim.src_dim = src_dim; 747 m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim); 748 jpg_job.encode_job.thumb_dim.crop = crop; 749 jpg_job.encode_job.thumb_index = thumb_frame->buf_idx; 750 } 751 752 // set rotation only when no online rotation or offline pp rotation is done before 753 754 if (!m_parent->needOnlineRotation()) { 755 jpg_job.encode_job.rotation = m_parent->getJpegRotation(); 756 } 757 ALOGV("%s: jpeg rotation is set to %d", __func__, jpg_job.encode_job.rotation); 758 759 // Find meta data frame. Meta data frame contains additional exif info 760 // which will be extracted and filled in by encoder. 761 //Note: In this version meta data will be null 762 //as we don't support bundling of snapshot and metadata streams. 763 764 mm_camera_buf_def_t *meta_frame = NULL; 765 for (int i = 0; i < jpeg_job_data->src_frame->num_bufs; i++) { 766 // look through input superbuf 767 if (jpeg_job_data->src_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 768 meta_frame = jpeg_job_data->src_frame->bufs[i]; 769 break; 770 } 771 } 772 if (meta_frame == NULL && jpeg_job_data->src_reproc_frame != NULL) { 773 // look through reprocess source superbuf 774 for (int i = 0; i < jpeg_job_data->src_reproc_frame->num_bufs; i++) { 775 if (jpeg_job_data->src_reproc_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) { 776 meta_frame = jpeg_job_data->src_reproc_frame->bufs[i]; 777 break; 778 } 779 } 780 } 781 if (meta_frame != NULL) { 782 // fill in meta data frame ptr 783 jpg_job.encode_job.p_metadata = (cam_metadata_info_t *)meta_frame->buffer; 784 } 785 786 //Start jpeg encoding 787 ret = mJpegHandle.start_job(&jpg_job, &jobId); 788 if (ret == NO_ERROR) { 789 // remember job info 790 jpeg_job_data->jobId = jobId; 791 } 792 793 ALOGD("%s : X", __func__); 794 return ret; 795} 796 797/*=========================================================================== 798 * FUNCTION : dataProcessRoutine 799 * 800 * DESCRIPTION: data process routine that handles input data either from input 801 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do 802 * reprocess. 803 * 804 * PARAMETERS : 805 * @data : user data ptr (QCamera3PostProcessor) 806 * 807 * RETURN : None 808 *==========================================================================*/ 809void *QCamera3PostProcessor::dataProcessRoutine(void *data) 810{ 811 int running = 1; 812 int ret; 813 uint8_t is_active = FALSE; 814 uint8_t needNewSess = TRUE; 815 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data; 816 QCameraCmdThread *cmdThread = &pme->m_dataProcTh; 817 818 ALOGD("%s: E", __func__); 819 do { 820 do { 821 ret = cam_sem_wait(&cmdThread->cmd_sem); 822 if (ret != 0 && errno != EINVAL) { 823 ALOGE("%s: cam_sem_wait error (%s)", 824 __func__, strerror(errno)); 825 return NULL; 826 } 827 } while (ret != 0); 828 829 // we got notified about new cmd avail in cmd queue 830 camera_cmd_type_t cmd = cmdThread->getCmd(); 831 switch (cmd) { 832 case CAMERA_CMD_TYPE_START_DATA_PROC: 833 ALOGD("%s: start data proc", __func__); 834 is_active = TRUE; 835 needNewSess = TRUE; 836 break; 837 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 838 { 839 ALOGD("%s: stop data proc", __func__); 840 is_active = FALSE; 841 842 // cancel all ongoing jpeg jobs 843 qcamera_jpeg_data_t *jpeg_job = 844 (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 845 while (jpeg_job != NULL) { 846 pme->mJpegHandle.abort_job(jpeg_job->jobId); 847 848 pme->releaseJpegJobData(jpeg_job); 849 free(jpeg_job); 850 851 jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(); 852 } 853 854 // destroy jpeg encoding session 855 if ( 0 < pme->mJpegSessionId ) { 856 pme->mJpegHandle.destroy_session(pme->mJpegSessionId); 857 pme->mJpegSessionId = 0; 858 } 859 860 // free jpeg exif obj 861 if (pme->m_pJpegExifObj != NULL) { 862 delete pme->m_pJpegExifObj; 863 pme->m_pJpegExifObj = NULL; 864 } 865 needNewSess = TRUE; 866 867 // flush ongoing postproc Queue 868 pme->m_ongoingPPQ.flush(); 869 870 // flush input jpeg Queue 871 pme->m_inputJpegQ.flush(); 872 873 // flush input Postproc Queue 874 pme->m_inputPPQ.flush(); 875 876 // flush input raw Queue 877 pme->m_inputRawQ.flush(); 878 879 // signal cmd is completed 880 cam_sem_post(&cmdThread->sync_sem); 881 } 882 break; 883 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 884 { 885 ALOGD("%s: Do next job, active is %d", __func__, is_active); 886 if (is_active == TRUE) { 887 // check if there is any ongoing jpeg jobs 888 if (pme->m_ongoingJpegQ.isEmpty()) { 889 // no ongoing jpeg job, we are fine to send jpeg encoding job 890 qcamera_jpeg_data_t *jpeg_job = 891 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue(); 892 893 if (NULL != jpeg_job) { 894 //TBD_later - play shutter sound 895 //pme->m_parent->playShutter(); 896 897 // add into ongoing jpeg job Q 898 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job); 899 ret = pme->encodeData(jpeg_job, needNewSess); 900 if (NO_ERROR != ret) { 901 // dequeue the last one 902 pme->m_ongoingJpegQ.dequeue(false); 903 904 pme->releaseJpegJobData(jpeg_job); 905 free(jpeg_job); 906 } 907 } 908 } 909 910 mm_camera_super_buf_t *pp_frame = 911 (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 912 if (NULL != pp_frame) { 913 qcamera_pp_data_t *pp_job = 914 (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t)); 915 if (pp_job != NULL) { 916 memset(pp_job, 0, sizeof(qcamera_pp_data_t)); 917 } else { 918 ALOGE("%s: no mem for qcamera_pp_data_t", __func__); 919 ret = -1; 920 } 921 922 if (0 != ret) { 923 // free pp_job 924 if (pp_job != NULL) { 925 free(pp_job); 926 } 927 // free frame 928 if (pp_frame != NULL) { 929 pme->releaseSuperBuf(pp_frame); 930 free(pp_frame); 931 } 932 } 933 } 934 } else { 935 // not active, simply return buf and do no op 936 mm_camera_super_buf_t *super_buf = 937 (mm_camera_super_buf_t *)pme->m_inputJpegQ.dequeue(); 938 if (NULL != super_buf) { 939 pme->releaseSuperBuf(super_buf); 940 free(super_buf); 941 } 942 super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue(); 943 if (NULL != super_buf) { 944 pme->releaseSuperBuf(super_buf); 945 free(super_buf); 946 } 947 super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue(); 948 if (NULL != super_buf) { 949 pme->releaseSuperBuf(super_buf); 950 free(super_buf); 951 } 952 } 953 } 954 break; 955 case CAMERA_CMD_TYPE_EXIT: 956 running = 0; 957 break; 958 default: 959 break; 960 } 961 } while (running); 962 ALOGD("%s: X", __func__); 963 return NULL; 964} 965 966/*=========================================================================== 967 * FUNCTION : getJpegPaddingReq 968 * 969 * DESCRIPTION: function to add an entry to exif data 970 * 971 * PARAMETERS : 972 * @padding_info : jpeg specific padding requirement 973 * 974 * RETURN : int32_t type of status 975 * NO_ERROR -- success 976 * none-zero failure code 977 *==========================================================================*/ 978int32_t QCamera3PostProcessor::getJpegPaddingReq(cam_padding_info_t &padding_info) 979{ 980 // TODO: hardcode for now, needs to query from mm-jpeg-interface 981 padding_info.width_padding = CAM_PAD_NONE; 982 padding_info.height_padding = CAM_PAD_TO_16; 983 padding_info.plane_padding = CAM_PAD_TO_WORD; 984 return NO_ERROR; 985} 986 987/*=========================================================================== 988 * FUNCTION : QCamera3Exif 989 * 990 * DESCRIPTION: constructor of QCamera3Exif 991 * 992 * PARAMETERS : None 993 * 994 * RETURN : None 995 *==========================================================================*/ 996QCamera3Exif::QCamera3Exif() 997 : m_nNumEntries(0) 998{ 999 memset(m_Entries, 0, sizeof(m_Entries)); 1000} 1001 1002/*=========================================================================== 1003 * FUNCTION : ~QCamera3Exif 1004 * 1005 * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr. 1006 * 1007 * PARAMETERS : None 1008 * 1009 * RETURN : None 1010 *==========================================================================*/ 1011QCamera3Exif::~QCamera3Exif() 1012{ 1013 for (uint32_t i = 0; i < m_nNumEntries; i++) { 1014 switch (m_Entries[i].tag_entry.type) { 1015 case EXIF_BYTE: 1016 { 1017 if (m_Entries[i].tag_entry.count > 1 && 1018 m_Entries[i].tag_entry.data._bytes != NULL) { 1019 free(m_Entries[i].tag_entry.data._bytes); 1020 m_Entries[i].tag_entry.data._bytes = NULL; 1021 } 1022 } 1023 break; 1024 case EXIF_ASCII: 1025 { 1026 if (m_Entries[i].tag_entry.data._ascii != NULL) { 1027 free(m_Entries[i].tag_entry.data._ascii); 1028 m_Entries[i].tag_entry.data._ascii = NULL; 1029 } 1030 } 1031 break; 1032 case EXIF_SHORT: 1033 { 1034 if (m_Entries[i].tag_entry.count > 1 && 1035 m_Entries[i].tag_entry.data._shorts != NULL) { 1036 free(m_Entries[i].tag_entry.data._shorts); 1037 m_Entries[i].tag_entry.data._shorts = NULL; 1038 } 1039 } 1040 break; 1041 case EXIF_LONG: 1042 { 1043 if (m_Entries[i].tag_entry.count > 1 && 1044 m_Entries[i].tag_entry.data._longs != NULL) { 1045 free(m_Entries[i].tag_entry.data._longs); 1046 m_Entries[i].tag_entry.data._longs = NULL; 1047 } 1048 } 1049 break; 1050 case EXIF_RATIONAL: 1051 { 1052 if (m_Entries[i].tag_entry.count > 1 && 1053 m_Entries[i].tag_entry.data._rats != NULL) { 1054 free(m_Entries[i].tag_entry.data._rats); 1055 m_Entries[i].tag_entry.data._rats = NULL; 1056 } 1057 } 1058 break; 1059 case EXIF_UNDEFINED: 1060 { 1061 if (m_Entries[i].tag_entry.data._undefined != NULL) { 1062 free(m_Entries[i].tag_entry.data._undefined); 1063 m_Entries[i].tag_entry.data._undefined = NULL; 1064 } 1065 } 1066 break; 1067 case EXIF_SLONG: 1068 { 1069 if (m_Entries[i].tag_entry.count > 1 && 1070 m_Entries[i].tag_entry.data._slongs != NULL) { 1071 free(m_Entries[i].tag_entry.data._slongs); 1072 m_Entries[i].tag_entry.data._slongs = NULL; 1073 } 1074 } 1075 break; 1076 case EXIF_SRATIONAL: 1077 { 1078 if (m_Entries[i].tag_entry.count > 1 && 1079 m_Entries[i].tag_entry.data._srats != NULL) { 1080 free(m_Entries[i].tag_entry.data._srats); 1081 m_Entries[i].tag_entry.data._srats = NULL; 1082 } 1083 } 1084 break; 1085 default: 1086 ALOGE("%s: Error, Unknown type",__func__); 1087 break; 1088 } 1089 } 1090} 1091 1092/*=========================================================================== 1093 * FUNCTION : addEntry 1094 * 1095 * DESCRIPTION: function to add an entry to exif data 1096 * 1097 * PARAMETERS : 1098 * @tagid : exif tag ID 1099 * @type : data type 1100 * @count : number of data in uint of its type 1101 * @data : input data ptr 1102 * 1103 * RETURN : int32_t type of status 1104 * NO_ERROR -- success 1105 * none-zero failure code 1106 *==========================================================================*/ 1107int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid, 1108 exif_tag_type_t type, 1109 uint32_t count, 1110 void *data) 1111{ 1112 int32_t rc = NO_ERROR; 1113 if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) { 1114 ALOGE("%s: Number of entries exceeded limit", __func__); 1115 return NO_MEMORY; 1116 } 1117 1118 m_Entries[m_nNumEntries].tag_id = tagid; 1119 m_Entries[m_nNumEntries].tag_entry.type = type; 1120 m_Entries[m_nNumEntries].tag_entry.count = count; 1121 m_Entries[m_nNumEntries].tag_entry.copy = 1; 1122 switch (type) { 1123 case EXIF_BYTE: 1124 { 1125 if (count > 1) { 1126 uint8_t *values = (uint8_t *)malloc(count); 1127 if (values == NULL) { 1128 ALOGE("%s: No memory for byte array", __func__); 1129 rc = NO_MEMORY; 1130 } else { 1131 memcpy(values, data, count); 1132 m_Entries[m_nNumEntries].tag_entry.data._bytes = values; 1133 } 1134 } else { 1135 m_Entries[m_nNumEntries].tag_entry.data._byte = 1136 *(uint8_t *)data; 1137 } 1138 } 1139 break; 1140 case EXIF_ASCII: 1141 { 1142 char *str = NULL; 1143 str = (char *)malloc(count + 1); 1144 if (str == NULL) { 1145 ALOGE("%s: No memory for ascii string", __func__); 1146 rc = NO_MEMORY; 1147 } else { 1148 memset(str, 0, count + 1); 1149 memcpy(str, data, count); 1150 m_Entries[m_nNumEntries].tag_entry.data._ascii = str; 1151 } 1152 } 1153 break; 1154 case EXIF_SHORT: 1155 { 1156 if (count > 1) { 1157 uint16_t *values = 1158 (uint16_t *)malloc(count * sizeof(uint16_t)); 1159 if (values == NULL) { 1160 ALOGE("%s: No memory for short array", __func__); 1161 rc = NO_MEMORY; 1162 } else { 1163 memcpy(values, data, count * sizeof(uint16_t)); 1164 m_Entries[m_nNumEntries].tag_entry.data._shorts =values; 1165 } 1166 } else { 1167 m_Entries[m_nNumEntries].tag_entry.data._short = 1168 *(uint16_t *)data; 1169 } 1170 } 1171 break; 1172 case EXIF_LONG: 1173 { 1174 if (count > 1) { 1175 uint32_t *values = 1176 (uint32_t *)malloc(count * sizeof(uint32_t)); 1177 if (values == NULL) { 1178 ALOGE("%s: No memory for long array", __func__); 1179 rc = NO_MEMORY; 1180 } else { 1181 memcpy(values, data, count * sizeof(uint32_t)); 1182 m_Entries[m_nNumEntries].tag_entry.data._longs = values; 1183 } 1184 } else { 1185 m_Entries[m_nNumEntries].tag_entry.data._long = 1186 *(uint32_t *)data; 1187 } 1188 } 1189 break; 1190 case EXIF_RATIONAL: 1191 { 1192 if (count > 1) { 1193 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t)); 1194 if (values == NULL) { 1195 ALOGE("%s: No memory for rational array", __func__); 1196 rc = NO_MEMORY; 1197 } else { 1198 memcpy(values, data, count * sizeof(rat_t)); 1199 m_Entries[m_nNumEntries].tag_entry.data._rats = values; 1200 } 1201 } else { 1202 m_Entries[m_nNumEntries].tag_entry.data._rat = 1203 *(rat_t *)data; 1204 } 1205 } 1206 break; 1207 case EXIF_UNDEFINED: 1208 { 1209 uint8_t *values = (uint8_t *)malloc(count); 1210 if (values == NULL) { 1211 ALOGE("%s: No memory for undefined array", __func__); 1212 rc = NO_MEMORY; 1213 } else { 1214 memcpy(values, data, count); 1215 m_Entries[m_nNumEntries].tag_entry.data._undefined = values; 1216 } 1217 } 1218 break; 1219 case EXIF_SLONG: 1220 { 1221 if (count > 1) { 1222 int32_t *values = 1223 (int32_t *)malloc(count * sizeof(int32_t)); 1224 if (values == NULL) { 1225 ALOGE("%s: No memory for signed long array", __func__); 1226 rc = NO_MEMORY; 1227 } else { 1228 memcpy(values, data, count * sizeof(int32_t)); 1229 m_Entries[m_nNumEntries].tag_entry.data._slongs =values; 1230 } 1231 } else { 1232 m_Entries[m_nNumEntries].tag_entry.data._slong = 1233 *(int32_t *)data; 1234 } 1235 } 1236 break; 1237 case EXIF_SRATIONAL: 1238 { 1239 if (count > 1) { 1240 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t)); 1241 if (values == NULL) { 1242 ALOGE("%s: No memory for sign rational array",__func__); 1243 rc = NO_MEMORY; 1244 } else { 1245 memcpy(values, data, count * sizeof(srat_t)); 1246 m_Entries[m_nNumEntries].tag_entry.data._srats = values; 1247 } 1248 } else { 1249 m_Entries[m_nNumEntries].tag_entry.data._srat = 1250 *(srat_t *)data; 1251 } 1252 } 1253 break; 1254 default: 1255 ALOGE("%s: Error, Unknown type",__func__); 1256 break; 1257 } 1258 1259 // Increase number of entries 1260 m_nNumEntries++; 1261 return rc; 1262} 1263 1264}; // namespace qcamera 1265