1 /* 2 ** Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17 /*#error uncomment this for compiler test!*/ 18 19 #define ALOG_NDEBUG 0 20 #define ALOG_NDDEBUG 0 21 #define ALOG_NIDEBUG 0 22 #define LOG_TAG "QCameraHWI_Still" 23 #include <utils/Log.h> 24 #include <utils/threads.h> 25 #include <fcntl.h> 26 #include <sys/mman.h> 27 #include <media/mediarecorder.h> 28 #include <math.h> 29 #include "QCameraHAL.h" 30 #include "QCameraHWI.h" 31 32 #define THUMBNAIL_DEFAULT_WIDTH 512 33 #define THUMBNAIL_DEFAULT_HEIGHT 384 34 /* following code implement the still image capture & encoding logic of this class*/ 35 namespace android { 36 37 typedef enum { 38 SNAPSHOT_STATE_ERROR, 39 SNAPSHOT_STATE_UNINIT, 40 SNAPSHOT_STATE_CH_ACQUIRED, 41 SNAPSHOT_STATE_BUF_NOTIF_REGD, 42 SNAPSHOT_STATE_BUF_INITIALIZED, 43 SNAPSHOT_STATE_INITIALIZED, 44 SNAPSHOT_STATE_IMAGE_CAPTURE_STRTD, 45 SNAPSHOT_STATE_YUV_RECVD, 46 SNAPSHOT_STATE_JPEG_ENCODING, 47 SNAPSHOT_STATE_JPEG_ENCODE_DONE, 48 SNAPSHOT_STATE_JPEG_COMPLETE_ENCODE_DONE, 49 50 /*Add any new state above*/ 51 SNAPSHOT_STATE_MAX 52 } snapshot_state_type_t; 53 54 55 //----------------------------------------------------------------------- 56 // Constants 57 //---------------------------------------------------------------------- 58 static const int PICTURE_FORMAT_JPEG = 1; 59 static const int PICTURE_FORMAT_RAW = 2; 60 static const int POSTVIEW_SMALL_HEIGHT = 144; 61 62 // --------------------------------------------------------------------------- 63 /* static functions*/ 64 // --------------------------------------------------------------------------- 65 66 67 68 /* TBD: Temp: to be removed*/ 69 static pthread_mutex_t g_s_mutex; 70 static int g_status = 0; 71 static pthread_cond_t g_s_cond_v; 72 73 static void mm_app_snapshot_done() 74 { 75 pthread_mutex_lock(&g_s_mutex); 76 g_status = true; 77 pthread_cond_signal(&g_s_cond_v); 78 pthread_mutex_unlock(&g_s_mutex); 79 } 80 81 static void mm_app_snapshot_wait() 82 { 83 pthread_mutex_lock(&g_s_mutex); 84 if(false == g_status) pthread_cond_wait(&g_s_cond_v, &g_s_mutex); 85 pthread_mutex_unlock(&g_s_mutex); 86 g_status = false; 87 } 88 89 static int mm_app_dump_snapshot_frame(char *filename, 90 const void *buffer, 91 uint32_t len) 92 { 93 char bufp[128]; 94 int file_fdp; 95 int rc = 0; 96 97 file_fdp = open(filename, O_RDWR | O_CREAT, 0777); 98 99 if (file_fdp < 0) { 100 rc = -1; 101 goto end; 102 } 103 write(file_fdp, 104 (const void *)buffer, len); 105 close(file_fdp); 106 end: 107 return rc; 108 } 109 110 /* Callback received when a frame is available after snapshot*/ 111 static void snapshot_notify_cb(mm_camera_ch_data_buf_t *recvd_frame, 112 void *user_data) 113 { 114 QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)user_data; 115 116 ALOGV("%s: E", __func__); 117 118 if (pme != NULL) { 119 pme->receiveRawPicture(recvd_frame); 120 } 121 else{ 122 ALOGW("%s: Snapshot obj NULL in callback", __func__); 123 } 124 125 ALOGV("%s: X", __func__); 126 127 } 128 129 /* Once we give frame for encoding, we get encoded jpeg image 130 fragments by fragment. We'll need to store them in a buffer 131 to form complete JPEG image */ 132 static void snapshot_jpeg_fragment_cb(uint8_t *ptr, 133 uint32_t size, 134 void *user_data) 135 { 136 QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)user_data; 137 138 ALOGV("%s: E",__func__); 139 if (pme != NULL) { 140 pme->receiveJpegFragment(ptr,size); 141 } 142 else 143 ALOGW("%s: Receive jpeg fragment cb obj Null", __func__); 144 145 ALOGV("%s: X",__func__); 146 } 147 148 /* This callback is received once the complete JPEG encoding is done */ 149 static void snapshot_jpeg_cb(jpeg_event_t event, void *user_data) 150 { 151 QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)user_data; 152 ALOGV("%s: E ",__func__); 153 154 switch(event) { 155 case JPEG_EVENT_DONE: 156 break; 157 case JPEG_EVENT_THUMBNAIL_DROPPED: 158 ALOGE("%s: Error in thumbnail encoding (event: %d) : X !!!", 159 __func__, event); 160 return; 161 case JPEG_EVENT_ERROR: 162 case JPEG_EVENT_ABORTED: 163 if (NULL != pme) { 164 pme->jpegErrorHandler(event); 165 if (!(pme->isZSLMode())) { 166 pme->stop(); 167 } 168 } 169 ALOGE("Error event handled from JPEG \n"); 170 return; 171 default: 172 ALOGE("Unsupported JPEG event %d \n", event); 173 break; 174 } 175 176 if (event != JPEG_EVENT_DONE) { 177 if (event == JPEG_EVENT_THUMBNAIL_DROPPED) { 178 ALOGE("%s: Error in thumbnail encoding (event: %d)!!!", 179 __func__, event); 180 ALOGV("%s: X",__func__); 181 return; 182 } 183 else { 184 ALOGE("%s: Error (event: %d) while jpeg encoding!!!", 185 __func__, event); 186 } 187 } 188 189 if (pme != NULL) { 190 pme->receiveCompleteJpegPicture(event); 191 ALOGV(" Completed issuing JPEG callback"); 192 /* deinit only if we are done taking requested number of snapshots */ 193 if (pme->getSnapshotState() == SNAPSHOT_STATE_JPEG_COMPLETE_ENCODE_DONE) { 194 ALOGV(" About to issue deinit callback"); 195 /* If it's ZSL Mode, we don't deinit now. We'll stop the polling thread and 196 deinit the channel/buffers only when we change the mode from zsl to 197 non-zsl. */ 198 if (!(pme->isZSLMode())) { 199 pme->stop(); 200 } 201 } 202 } 203 else 204 ALOGW("%s: Receive jpeg cb Obj Null", __func__); 205 206 207 ALOGV("%s: X",__func__); 208 } 209 210 // --------------------------------------------------------------------------- 211 /* private functions*/ 212 // --------------------------------------------------------------------------- 213 214 void QCameraStream_Snapshot:: 215 receiveJpegFragment(uint8_t *ptr, uint32_t size) 216 { 217 ALOGV("%s: E", __func__); 218 #if 0 219 if (mJpegHeap != NULL) { 220 ALOGE("%s: Copy jpeg...", __func__); 221 memcpy((uint8_t *)mJpegHeap->mHeap->base()+ mJpegOffset, ptr, size); 222 mJpegOffset += size; 223 } 224 else { 225 ALOGE("%s: mJpegHeap is NULL!", __func__); 226 } 227 #else 228 if(mHalCamCtrl->mJpegMemory.camera_memory[0] != NULL && ptr != NULL && size > 0) { 229 memcpy((uint8_t *)((uint32_t)mHalCamCtrl->mJpegMemory.camera_memory[0]->data + mJpegOffset), ptr, size); 230 mJpegOffset += size; 231 232 233 /* 234 memcpy((uint8_t *)((uint32_t)mHalCamCtrl->mJpegMemory.camera_memory[0]->data + mJpegOffset), ptr, size); 235 mJpegOffset += size; 236 */ 237 } else { 238 ALOGE("%s: mJpegHeap is NULL!", __func__); 239 } 240 241 242 #endif 243 244 ALOGV("%s: X", __func__); 245 } 246 247 void QCameraStream_Snapshot::jpegErrorHandler(jpeg_event_t event) 248 { 249 ALOGV("%s: E", __func__); 250 camera_memory_t *data = mHalCamCtrl->mGetMemory(-1, 1, 1, NULL); 251 mStopCallbackLock.lock( ); 252 if(mCurrentFrameEncoded) { 253 free(mCurrentFrameEncoded); 254 mCurrentFrameEncoded = NULL; 255 } 256 setSnapshotState(SNAPSHOT_STATE_ERROR); 257 if (!mSnapshotQueue.isEmpty()) { 258 ALOGV("%s: JPEG Queue not empty. flush the queue in " 259 "error case.", __func__); 260 mSnapshotQueue.flush(); 261 } 262 mStopCallbackLock.unlock( ); 263 if (NULL != mHalCamCtrl->mDataCb) 264 mHalCamCtrl->mDataCb (CAMERA_MSG_COMPRESSED_IMAGE, 265 data, 0, NULL,mHalCamCtrl->mCallbackCookie); 266 if(NULL != data) data->release(data); 267 ALOGV("%s: X", __func__); 268 } 269 270 void QCameraStream_Snapshot:: 271 receiveCompleteJpegPicture(jpeg_event_t event) 272 { 273 int msg_type = CAMERA_MSG_COMPRESSED_IMAGE; 274 ALOGV("%s: E", __func__); 275 camera_memory_t *encodedMem = NULL; 276 camera_data_callback jpg_data_cb = NULL; 277 bool fail_cb_flag = false; 278 279 if (mHalCamCtrl->mHdrMode == HDR_MODE) 280 hdrJpegCount++; 281 282 mStopCallbackLock.lock( ); 283 if(!mActive && !isLiveSnapshot()) { 284 ALOGE("%s : Cancel Picture",__func__); 285 fail_cb_flag = true; 286 goto end; 287 } 288 289 if(mCurrentFrameEncoded!=NULL /*&& !isLiveSnapshot()*/){ 290 ALOGV("<DEBUG>: Calling buf done for snapshot buffer"); 291 cam_evt_buf_done(mCameraId, mCurrentFrameEncoded); 292 } 293 mHalCamCtrl->dumpFrameToFile(mHalCamCtrl->mJpegMemory.camera_memory[0]->data, mJpegOffset, (char *)"debug", (char *)"jpg", 0); 294 295 end: 296 msg_type = CAMERA_MSG_COMPRESSED_IMAGE; 297 if (mHalCamCtrl->mDataCb && (mHalCamCtrl->mMsgEnabled & msg_type)) { 298 jpg_data_cb = mHalCamCtrl->mDataCb; 299 }else{ 300 ALOGE("%s: JPEG callback was cancelled--not delivering image.", __func__); 301 } 302 setSnapshotState(SNAPSHOT_STATE_JPEG_ENCODE_DONE); 303 mNumOfRecievedJPEG++; 304 mHalCamCtrl->deinitExifData(); 305 306 /* free the resource we allocated to maintain the structure */ 307 //mm_camera_do_munmap(main_fd, (void *)main_buffer_addr, mSnapshotStreamBuf.frame_len); 308 if(mCurrentFrameEncoded) { 309 free(mCurrentFrameEncoded); 310 mCurrentFrameEncoded = NULL; 311 } 312 /* Before leaving check the jpeg queue. If it's not empty give the available 313 frame for encoding*/ 314 if (!mSnapshotQueue.isEmpty()) { 315 ALOGV("%s: JPEG Queue not empty. Dequeue and encode.", __func__); 316 mm_camera_ch_data_buf_t* buf = 317 (mm_camera_ch_data_buf_t *)mSnapshotQueue.dequeue(); 318 //encodeDisplayAndSave(buf, 1); 319 if ( NO_ERROR != encodeDisplayAndSave(buf, 1)){ 320 fail_cb_flag = true; 321 } 322 } else if (mNumOfSnapshot == mNumOfRecievedJPEG ) { /* finished */ 323 ALOGV("nusnap %d, mNumjpeg %d", mNumOfSnapshot, mNumOfRecievedJPEG); 324 ALOGV("%s: Before omxJpegFinish", __func__); 325 omxJpegFinish(); 326 ALOGV("%s: After omxJpegFinish", __func__); 327 /* getRemainingSnapshots call will give us number of snapshots still 328 remaining after flushing current zsl buffer once*/ 329 ALOGV("%s: Complete JPEG Encoding Done!", __func__); 330 setSnapshotState(SNAPSHOT_STATE_JPEG_COMPLETE_ENCODE_DONE); 331 mBurstModeFlag = false; 332 mSnapshotQueue.flush(); 333 mNumOfRecievedJPEG = 0; 334 /* in case of zsl, we need to reset some of the zsl attributes */ 335 if (isZSLMode()){ 336 ALOGV("%s: Resetting the ZSL attributes", __func__); 337 setZSLChannelAttribute(); 338 } 339 if (!isZSLMode() && !isLiveSnapshot()){ 340 //Stop polling before calling datacb for if not ZSL mode 341 stopPolling(); 342 } 343 344 } else { 345 ALOGV("%s: mNumOfRecievedJPEG(%d), mNumOfSnapshot(%d)", __func__, mNumOfRecievedJPEG, mNumOfSnapshot); 346 } 347 if(fail_cb_flag && mHalCamCtrl->mDataCb && 348 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) { 349 /* get picture failed. Give jpeg callback with NULL data 350 * to the application to restore to preview mode 351 */ 352 jpg_data_cb = mHalCamCtrl->mDataCb; 353 } 354 if(mHalCamCtrl->mHdrMode == HDR_MODE && (hdrJpegCount%2) != 0){ 355 mStopCallbackLock.unlock( ); 356 mJpegOffset = 0; 357 return; 358 } 359 if(!fail_cb_flag) { 360 camera_memory_t *encodedMem = mHalCamCtrl->mGetMemory( 361 mHalCamCtrl->mJpegMemory.fd[0], mJpegOffset, 1, mHalCamCtrl); 362 if (!encodedMem || !encodedMem->data) { 363 ALOGE("%s: mGetMemory failed.\n", __func__); 364 } 365 memcpy(encodedMem->data, mHalCamCtrl->mJpegMemory.camera_memory[0]->data, mJpegOffset ); 366 mStopCallbackLock.unlock( ); 367 368 if ((mActive || isLiveSnapshot()) && jpg_data_cb != NULL) { 369 ALOGV("%s: Calling upperlayer callback to store JPEG image", __func__); 370 jpg_data_cb (msg_type,encodedMem, 0, NULL,mHalCamCtrl->mCallbackCookie); 371 } 372 encodedMem->release( encodedMem ); 373 jpg_data_cb = NULL; 374 }else{ 375 ALOGV("Image Encoding Failed... Notify Upper layer"); 376 mStopCallbackLock.unlock( ); 377 if((mActive || isLiveSnapshot()) && jpg_data_cb != NULL) { 378 jpg_data_cb (CAMERA_MSG_COMPRESSED_IMAGE,NULL, 0, NULL, 379 mHalCamCtrl->mCallbackCookie); 380 } 381 } 382 //reset jpeg_offset 383 mJpegOffset = 0; 384 385 if(isLiveSnapshot() && mHalCamCtrl->mStateLiveshot) { 386 deInitBuffer(); 387 } 388 mHalCamCtrl->mStateLiveshot = false; 389 390 ALOGV("%s: X", __func__); 391 } 392 393 status_t QCameraStream_Snapshot:: 394 configSnapshotDimension(cam_ctrl_dimension_t* dim) 395 { 396 bool matching = true; 397 cam_format_t img_format; 398 status_t ret = NO_ERROR; 399 ALOGV("%s: E", __func__); 400 401 ALOGV("%s:Passed picture size: %d X %d", __func__, 402 dim->picture_width, dim->picture_height); 403 ALOGV("%s:Passed postview size: %d X %d", __func__, 404 dim->ui_thumbnail_width, dim->ui_thumbnail_height); 405 406 /* First check if the picture resolution is the same, if not, change it*/ 407 mHalCamCtrl->getPictureSize(&mPictureWidth, &mPictureHeight); 408 ALOGV("%s: Picture size received: %d x %d", __func__, 409 mPictureWidth, mPictureHeight); 410 411 mPostviewWidth = mHalCamCtrl->mParameters.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); 412 mPostviewHeight = mHalCamCtrl->mParameters.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); 413 /*If application requested thumbnail size to be (0,0) 414 then configure second outout to a default size. 415 Jpeg encoder will drop thumbnail as reflected in encodeParams. 416 */ 417 mDropThumbnail = false; 418 if (mPostviewWidth == 0 && mPostviewHeight == 0) { 419 mPostviewWidth = THUMBNAIL_DEFAULT_WIDTH; 420 mPostviewHeight = THUMBNAIL_DEFAULT_HEIGHT; 421 mDropThumbnail = true; 422 } 423 424 ALOGV("%s: Postview size received: %d x %d", __func__, 425 mPostviewWidth, mPostviewHeight); 426 427 matching = (mPictureWidth == dim->picture_width) && 428 (mPictureHeight == dim->picture_height); 429 matching &= (dim->ui_thumbnail_width == mPostviewWidth) && 430 (dim->ui_thumbnail_height == mPostviewHeight); 431 432 /* picture size currently set do not match with the one wanted 433 by user.*/ 434 if (!matching) { 435 if (!isZSLMode() && (mPictureWidth < mPostviewWidth || mPictureHeight < mPostviewHeight)) { 436 //Changes to Handle VFE limitation. 437 mActualPictureWidth = mPictureWidth; 438 mActualPictureHeight = mPictureHeight; 439 mPictureWidth = mPostviewWidth; 440 mPictureHeight = mPostviewHeight; 441 mJpegDownscaling = true; 442 }else{ 443 mJpegDownscaling = false; 444 } 445 dim->picture_width = mPictureWidth; 446 dim->picture_height = mPictureHeight; 447 dim->ui_thumbnail_height = mThumbnailHeight = mPostviewHeight; 448 dim->ui_thumbnail_width = mThumbnailWidth = mPostviewWidth; 449 } 450 #if 0 451 img_format = mHalCamCtrl->getPreviewFormat(); 452 if (img_format) { 453 matching &= (img_format == dim->main_img_format); 454 if (!matching) { 455 dim->main_img_format = img_format; 456 dim->thumb_format = img_format; 457 } 458 } 459 #endif 460 if (!matching) { 461 ALOGV("%s: Image Sizes before set parm call: main: %dx%d thumbnail: %dx%d", 462 __func__, 463 dim->picture_width, dim->picture_height, 464 dim->ui_thumbnail_width, dim->ui_thumbnail_height); 465 466 ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,dim); 467 if (NO_ERROR != ret) { 468 ALOGE("%s: error - can't config snapshot parms!", __func__); 469 ret = FAILED_TRANSACTION; 470 goto end; 471 } 472 } 473 /* set_parm will return corrected dimension based on aspect ratio and 474 ceiling size */ 475 mPictureWidth = dim->picture_width; 476 mPictureHeight = dim->picture_height; 477 mPostviewHeight = mThumbnailHeight = dim->ui_thumbnail_height; 478 mPostviewWidth = mThumbnailWidth = dim->ui_thumbnail_width; 479 mPictureFormat= dim->main_img_format; 480 mThumbnailFormat = dim->thumb_format; 481 482 ALOGV("%s: Image Format: %d", __func__, dim->main_img_format); 483 ALOGV("%s: Image Sizes: main: %dx%d thumbnail: %dx%d", __func__, 484 dim->picture_width, dim->picture_height, 485 dim->ui_thumbnail_width, dim->ui_thumbnail_height); 486 end: 487 ALOGV("%s: X", __func__); 488 return ret; 489 } 490 491 status_t QCameraStream_Snapshot:: 492 initRawSnapshotChannel(cam_ctrl_dimension_t *dim, 493 int num_of_snapshots) 494 { 495 status_t ret = NO_ERROR; 496 mm_camera_ch_image_fmt_parm_t fmt; 497 mm_camera_channel_attr_t ch_attr; 498 cam_format_t raw_fmt; 499 500 mm_camera_raw_streaming_type_t raw_stream_type = 501 MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE; 502 503 ALOGV("%s: E", __func__); 504 505 /* Initialize stream - set format, acquire channel */ 506 /*TBD: Currently we only support single raw capture*/ 507 ALOGV("num_of_snapshots = %d",num_of_snapshots); 508 if (num_of_snapshots == 1) { 509 raw_stream_type = MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE; 510 } 511 512 /* Set channel attribute */ 513 ALOGV("%s: Set Raw Snapshot Channel attribute", __func__); 514 memset(&ch_attr, 0, sizeof(ch_attr)); 515 ch_attr.type = MM_CAMERA_CH_ATTR_RAW_STREAMING_TYPE; 516 ch_attr.raw_streaming_mode = raw_stream_type; 517 518 if( NO_ERROR != 519 cam_ops_ch_set_attr(mCameraId, MM_CAMERA_CH_RAW, &ch_attr)) { 520 ALOGV("%s: Failure setting Raw channel attribute.", __func__); 521 ret = FAILED_TRANSACTION; 522 goto end; 523 } 524 525 ret = cam_config_get_parm(mCameraId, 526 MM_CAMERA_PARM_RAW_SNAPSHOT_FMT, &raw_fmt); 527 if (NO_ERROR != ret) { 528 ALOGE("%s: error - can't get raw snapshot fmt!", __func__); 529 ret = FAILED_TRANSACTION; 530 goto end; 531 } 532 533 memset(&fmt, 0, sizeof(mm_camera_ch_image_fmt_parm_t)); 534 fmt.ch_type = MM_CAMERA_CH_RAW; 535 fmt.def.fmt = raw_fmt; 536 fmt.def.dim.width = dim->raw_picture_width; 537 fmt.def.dim.height = dim->raw_picture_height; 538 539 540 ALOGV("%s: Raw snapshot channel fmt: %d", __func__, 541 fmt.def.fmt); 542 ALOGV("%s: Raw snapshot resolution: %dX%d", __func__, 543 dim->raw_picture_width, dim->raw_picture_height); 544 545 ALOGV("%s: Set Raw Snapshot channel image format", __func__); 546 ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_CH_IMAGE_FMT, &fmt); 547 if (NO_ERROR != ret) { 548 ALOGE("%s: Set Raw Snapshot Channel format err=%d\n", __func__, ret); 549 ret = FAILED_TRANSACTION; 550 goto end; 551 } 552 553 end: 554 if (ret != NO_ERROR) { 555 handleError(); 556 } 557 ALOGV("%s: X", __func__); 558 return ret; 559 560 } 561 562 status_t QCameraStream_Snapshot:: 563 setZSLChannelAttribute(void) 564 { 565 status_t ret = NO_ERROR; 566 mm_camera_channel_attr_t ch_attr; 567 ALOGV("%s: E", __func__); 568 569 memset(&ch_attr, 0, sizeof(mm_camera_channel_attr_t)); 570 ch_attr.type = MM_CAMERA_CH_ATTR_BUFFERING_FRAME; 571 ch_attr.buffering_frame.look_back = mHalCamCtrl->getZSLBackLookCount(); 572 ch_attr.buffering_frame.water_mark = mHalCamCtrl->getZSLQueueDepth(); 573 ch_attr.buffering_frame.interval = mHalCamCtrl->getZSLBurstInterval( ); 574 ALOGV("%s: ZSL queue_depth = %d, back_look_count = %d", __func__, 575 ch_attr.buffering_frame.water_mark, 576 ch_attr.buffering_frame.look_back); 577 if( NO_ERROR != 578 cam_ops_ch_set_attr(mCameraId, MM_CAMERA_CH_SNAPSHOT, &ch_attr)) { 579 ALOGV("%s: Failure setting ZSL channel attribute.", __func__); 580 ret = FAILED_TRANSACTION; 581 goto end; 582 } 583 end: 584 ALOGV("%s: X", __func__); 585 return ret; 586 } 587 588 status_t QCameraStream_Snapshot:: 589 initSnapshotFormat(cam_ctrl_dimension_t *dim) 590 { 591 status_t ret = NO_ERROR; 592 mm_camera_ch_image_fmt_parm_t fmt; 593 594 ALOGV("%s: E", __func__); 595 596 /* For ZSL mode we'll need to set channel attribute */ 597 if (isZSLMode()) { 598 ret = setZSLChannelAttribute(); 599 if (ret != NO_ERROR) { 600 goto end; 601 } 602 } 603 604 memset(&fmt, 0, sizeof(mm_camera_ch_image_fmt_parm_t)); 605 fmt.ch_type = MM_CAMERA_CH_SNAPSHOT; 606 fmt.snapshot.main.fmt = dim->main_img_format; 607 fmt.snapshot.main.dim.width = dim->picture_width; 608 fmt.snapshot.main.dim.height = dim->picture_height; 609 610 fmt.snapshot.thumbnail.fmt = dim->thumb_format; 611 fmt.snapshot.thumbnail.dim.width = dim->ui_thumbnail_width; 612 fmt.snapshot.thumbnail.dim.height = dim->ui_thumbnail_height; 613 614 ALOGV("%s: Snapshot channel fmt = main: %d thumbnail: %d", __func__, 615 dim->main_img_format, dim->thumb_format); 616 ALOGV("%s: Snapshot channel resolution = main: %dX%d thumbnail: %dX%d", 617 __func__, dim->picture_width, dim->picture_height, 618 dim->ui_thumbnail_width, dim->ui_thumbnail_height); 619 620 ALOGV("%s: Set Snapshot channel image format", __func__); 621 ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_CH_IMAGE_FMT, &fmt); 622 if (NO_ERROR != ret) { 623 ALOGE("%s: Set Snapshot Channel format err=%d\n", __func__, ret); 624 ret = FAILED_TRANSACTION; 625 goto end; 626 } 627 628 end: 629 if (ret != NO_ERROR) { 630 handleError(); 631 } 632 ALOGV("%s: X", __func__); 633 return ret; 634 635 } 636 637 void QCameraStream_Snapshot:: 638 deinitSnapshotChannel(mm_camera_channel_type_t ch_type) 639 { 640 ALOGV("%s: E", __func__); 641 642 /* unreg buf notify*/ 643 if (getSnapshotState() >= SNAPSHOT_STATE_BUF_NOTIF_REGD){ 644 if (NO_ERROR != cam_evt_register_buf_notify(mCameraId, 645 ch_type, NULL,(mm_camera_register_buf_cb_type_t)NULL,NULL, this)) { 646 ALOGE("%s: Failure to unregister buf notification", __func__); 647 } 648 } 649 650 if (getSnapshotState() >= SNAPSHOT_STATE_CH_ACQUIRED) { 651 ALOGV("%s: Release snapshot channel", __func__); 652 cam_ops_ch_release(mCameraId, ch_type); 653 } 654 655 ALOGV("%s: X",__func__); 656 } 657 658 status_t QCameraStream_Snapshot:: 659 initRawSnapshotBuffers(cam_ctrl_dimension_t *dim, int num_of_buf) 660 { 661 status_t ret = NO_ERROR; 662 struct msm_frame *frame; 663 uint32_t frame_len; 664 uint8_t num_planes; 665 uint32_t planes[VIDEO_MAX_PLANES]; 666 mm_camera_reg_buf_t reg_buf; 667 cam_format_t raw_fmt; 668 669 ALOGV("%s: E", __func__); 670 memset(®_buf, 0, sizeof(mm_camera_reg_buf_t)); 671 memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf)); 672 673 if ((num_of_buf == 0) || (num_of_buf > MM_CAMERA_MAX_NUM_FRAMES)) { 674 ALOGE("%s: Invalid number of buffers (=%d) requested!", __func__, num_of_buf); 675 ret = BAD_VALUE; 676 goto end; 677 } 678 679 reg_buf.def.buf.mp = new mm_camera_mp_buf_t[num_of_buf]; 680 if (!reg_buf.def.buf.mp) { 681 ALOGE("%s Error allocating memory for mplanar struct ", __func__); 682 ret = NO_MEMORY; 683 goto end; 684 } 685 memset(reg_buf.def.buf.mp, 0, num_of_buf * sizeof(mm_camera_mp_buf_t)); 686 687 ret = cam_config_get_parm(mCameraId, 688 MM_CAMERA_PARM_RAW_SNAPSHOT_FMT, &raw_fmt); 689 if (NO_ERROR != ret) { 690 ALOGE("%s: error - can't get raw snapshot fmt!", __func__); 691 ret = FAILED_TRANSACTION; 692 goto end; 693 } 694 695 /* Get a frame len for buffer to be allocated*/ 696 frame_len = mm_camera_get_msm_frame_len(raw_fmt, 697 myMode, 698 dim->raw_picture_width, 699 dim->raw_picture_height, 700 OUTPUT_TYPE_S, 701 &num_planes, planes); 702 703 if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mRawMemory, num_of_buf, 704 frame_len, 0, planes[0], MSM_PMEM_RAW_MAINIMG, 705 &mSnapshotStreamBuf, ®_buf.def, 706 num_planes, planes) < 0) { 707 ret = NO_MEMORY; 708 goto end; 709 } 710 711 /* register the streaming buffers for the channel*/ 712 reg_buf.ch_type = MM_CAMERA_CH_RAW; 713 reg_buf.def.num = mSnapshotStreamBuf.num; 714 715 ret = cam_config_prepare_buf(mCameraId, ®_buf); 716 if(ret != NO_ERROR) { 717 ALOGV("%s:reg snapshot buf err=%d\n", __func__, ret); 718 ret = FAILED_TRANSACTION; 719 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mRawMemory); 720 goto end; 721 } 722 723 /* If we have reached here successfully, we have allocated buffer. 724 Set state machine.*/ 725 setSnapshotState(SNAPSHOT_STATE_BUF_INITIALIZED); 726 727 end: 728 /* If it's error, we'll need to do some needful */ 729 if (ret != NO_ERROR) { 730 handleError(); 731 } 732 if (reg_buf.def.buf.mp) 733 delete []reg_buf.def.buf.mp; 734 ALOGV("%s: X", __func__); 735 return ret; 736 } 737 738 status_t QCameraStream_Snapshot::deinitRawSnapshotBuffers(void) 739 { 740 int ret = NO_ERROR; 741 ALOGV("%s: E", __func__); 742 743 int err = getSnapshotState(); 744 745 /* deinit buffers only if we have already allocated */ 746 if (err >= SNAPSHOT_STATE_BUF_INITIALIZED || err == SNAPSHOT_STATE_ERROR){ 747 ALOGV("%s: Unpreparing Snapshot Buffer", __func__); 748 ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_RAW); 749 if(ret != NO_ERROR) { 750 ALOGE("%s:Unreg Raw snapshot buf err=%d\n", __func__, ret); 751 ret = FAILED_TRANSACTION; 752 goto end; 753 } 754 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mRawMemory); 755 } 756 757 end: 758 ALOGV("%s: X", __func__); 759 return ret; 760 } 761 762 status_t QCameraStream_Snapshot:: 763 initSnapshotBuffers(cam_ctrl_dimension_t *dim, int num_of_buf) 764 { 765 status_t ret = NO_ERROR; 766 struct msm_frame *frame; 767 uint32_t frame_len, y_off, cbcr_off; 768 uint8_t num_planes; 769 uint32_t planes[VIDEO_MAX_PLANES]; 770 mm_camera_reg_buf_t reg_buf; 771 int rotation = 0; 772 773 ALOGV("%s: E", __func__); 774 memset(®_buf, 0, sizeof(mm_camera_reg_buf_t)); 775 memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf)); 776 777 if ((num_of_buf == 0) || (num_of_buf > MM_CAMERA_MAX_NUM_FRAMES)) { 778 ALOGE("%s: Invalid number of buffers (=%d) requested!", 779 __func__, num_of_buf); 780 ret = BAD_VALUE; 781 goto end; 782 } 783 784 ALOGV("%s: Mode: %d Num_of_buf: %d ImageSizes: main: %dx%d thumb: %dx%d", 785 __func__, myMode, num_of_buf, 786 dim->picture_width, dim->picture_height, 787 dim->ui_thumbnail_width, dim->ui_thumbnail_height); 788 789 reg_buf.snapshot.main.buf.mp = new mm_camera_mp_buf_t[num_of_buf]; 790 if (!reg_buf.snapshot.main.buf.mp) { 791 ALOGE("%s Error allocating memory for mplanar struct ", __func__); 792 ret = NO_MEMORY; 793 goto end; 794 } 795 memset(reg_buf.snapshot.main.buf.mp, 0, 796 num_of_buf * sizeof(mm_camera_mp_buf_t)); 797 if (!isFullSizeLiveshot()) { 798 reg_buf.snapshot.thumbnail.buf.mp = new mm_camera_mp_buf_t[num_of_buf]; 799 if (!reg_buf.snapshot.thumbnail.buf.mp) { 800 ALOGE("%s Error allocating memory for mplanar struct ", __func__); 801 ret = NO_MEMORY; 802 goto end; 803 } 804 memset(reg_buf.snapshot.thumbnail.buf.mp, 0, 805 num_of_buf * sizeof(mm_camera_mp_buf_t)); 806 } 807 /* Number of buffers to be set*/ 808 /* Set the JPEG Rotation here since get_buffer_offset needs 809 * the value of rotation.*/ 810 mHalCamCtrl->setJpegRotation(isZSLMode()); 811 if(!isZSLMode()) 812 rotation = mHalCamCtrl->getJpegRotation(); 813 else 814 rotation = 0; 815 if(rotation != dim->rotation) { 816 dim->rotation = rotation; 817 ret = cam_config_set_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, dim); 818 } 819 820 if(isLiveSnapshot()) { 821 ret = cam_config_set_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, dim); 822 } 823 num_planes = 2; 824 planes[0] = dim->picture_frame_offset.mp[0].len; 825 planes[1] = dim->picture_frame_offset.mp[1].len; 826 frame_len = dim->picture_frame_offset.frame_len; 827 y_off = dim->picture_frame_offset.mp[0].offset; 828 cbcr_off = dim->picture_frame_offset.mp[1].offset; 829 ALOGV("%s: main image: rotation = %d, yoff = %d, cbcroff = %d, size = %d, width = %d, height = %d", 830 __func__, dim->rotation, y_off, cbcr_off, frame_len, dim->picture_width, dim->picture_height); 831 if (mHalCamCtrl->initHeapMem (&mHalCamCtrl->mJpegMemory, 1, frame_len, 0, cbcr_off, 832 MSM_PMEM_MAX, NULL, NULL, num_planes, planes) < 0) { 833 ALOGE("%s: Error allocating JPEG memory", __func__); 834 ret = NO_MEMORY; 835 goto end; 836 } 837 if(!isLiveSnapshot()) { 838 if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mSnapshotMemory, num_of_buf, 839 frame_len, y_off, cbcr_off, MSM_PMEM_MAINIMG, &mSnapshotStreamBuf, 840 ®_buf.snapshot.main, num_planes, planes) < 0) { 841 ret = NO_MEMORY; 842 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory); 843 goto end; 844 }; 845 num_planes = 2; 846 planes[0] = dim->thumb_frame_offset.mp[0].len; 847 planes[1] = dim->thumb_frame_offset.mp[1].len; 848 frame_len = planes[0] + planes[1]; 849 if (!isFullSizeLiveshot()) { 850 y_off = dim->thumb_frame_offset.mp[0].offset; 851 cbcr_off = dim->thumb_frame_offset.mp[1].offset; 852 ALOGV("%s: thumbnail: rotation = %d, yoff = %d, cbcroff = %d, size = %d, width = %d, height = %d", 853 __func__, dim->rotation, y_off, cbcr_off, frame_len, 854 dim->thumbnail_width, dim->thumbnail_height); 855 856 if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mThumbnailMemory, num_of_buf, 857 frame_len, y_off, cbcr_off, MSM_PMEM_THUMBNAIL, &mPostviewStreamBuf, 858 ®_buf.snapshot.thumbnail, num_planes, planes) < 0) { 859 ret = NO_MEMORY; 860 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mSnapshotMemory); 861 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory); 862 goto end; 863 } 864 } 865 /* register the streaming buffers for the channel*/ 866 reg_buf.ch_type = MM_CAMERA_CH_SNAPSHOT; 867 reg_buf.snapshot.main.num = mSnapshotStreamBuf.num; 868 869 if (!isFullSizeLiveshot()) 870 reg_buf.snapshot.thumbnail.num = mPostviewStreamBuf.num; 871 else 872 reg_buf.snapshot.thumbnail.num = 0; 873 874 ret = cam_config_prepare_buf(mCameraId, ®_buf); 875 if(ret != NO_ERROR) { 876 ALOGE("%s:reg snapshot buf err=%d\n", __func__, ret); 877 ret = FAILED_TRANSACTION; 878 if (!isFullSizeLiveshot()){ 879 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mThumbnailMemory); 880 } 881 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mSnapshotMemory); 882 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory); 883 goto end; 884 } 885 } 886 887 /* If we have reached here successfully, we have allocated buffer. 888 Set state machine.*/ 889 setSnapshotState(SNAPSHOT_STATE_BUF_INITIALIZED); 890 end: 891 if (ret != NO_ERROR) { 892 handleError(); 893 } 894 if (reg_buf.snapshot.main.buf.mp) 895 delete []reg_buf.snapshot.main.buf.mp; 896 if (reg_buf.snapshot.thumbnail.buf.mp) 897 delete []reg_buf.snapshot.thumbnail.buf.mp; 898 ALOGV("%s: X", __func__); 899 return ret; 900 } 901 902 status_t QCameraStream_Snapshot:: 903 deinitSnapshotBuffers(void) 904 { 905 int ret = NO_ERROR; 906 ALOGV("%s: E", __func__); 907 908 int err = getSnapshotState(); 909 /* Deinit only if we have already initialized*/ 910 if (err >= SNAPSHOT_STATE_BUF_INITIALIZED || err == SNAPSHOT_STATE_ERROR){ 911 912 if(!isLiveSnapshot()) { 913 ALOGV("%s: Unpreparing Snapshot Buffer", __func__); 914 ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_SNAPSHOT); 915 if(ret != NO_ERROR) { 916 ALOGE("%s:unreg snapshot buf err=%d\n", __func__, ret); 917 ret = FAILED_TRANSACTION; 918 goto end; 919 } 920 } 921 922 /* Clear main and thumbnail heap*/ 923 if(!isLiveSnapshot()) { 924 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mSnapshotMemory); 925 if (!isFullSizeLiveshot()) 926 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mThumbnailMemory); 927 } 928 mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory); 929 } 930 end: 931 ALOGV("%s: X", __func__); 932 return ret; 933 } 934 935 void QCameraStream_Snapshot::deInitBuffer(void) 936 { 937 mm_camera_channel_type_t ch_type; 938 939 ALOGV("%s: E", __func__); 940 941 if( getSnapshotState() == SNAPSHOT_STATE_UNINIT) { 942 ALOGV("%s: Already deinit'd!", __func__); 943 return; 944 } 945 946 if (mSnapshotFormat == PICTURE_FORMAT_RAW) { 947 /* deinit buffer */ 948 deinitRawSnapshotBuffers(); 949 } 950 else 951 { 952 if ((!isZSLMode() && !isLiveSnapshot()) && 953 ((mHalCamCtrl->getHDRMode() == HDR_MODE) || (mHalCamCtrl->isWDenoiseEnabled()))) { 954 /*register main and thumbnail buffers at back-end for frameproc*/ 955 for (int i = 0; i < mHalCamCtrl->mSnapshotMemory.buffer_count; i++) { 956 if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i, mCameraId, 957 CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) { 958 ALOGE("%s: unmapping Main image Buffer for HDR and Denoise", __func__); 959 } 960 if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, i, mCameraId, 961 CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) { 962 ALOGE("%s: unmapping Thumbnail buffer for HDR and Denoise", __func__); 963 } 964 } 965 } 966 if (isZSLMode()) { 967 /*register main and thumbnail buffers at back-end for frameproc*/ 968 for (int i = 0; i < mHalCamCtrl->mSnapshotMemory.buffer_count; i++) { 969 if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i, mCameraId, 970 CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) { 971 ALOGE("%s: unmapping Main image Buffer for ZSL", __func__); 972 } 973 } 974 } 975 976 deinitSnapshotBuffers(); 977 } 978 979 980 /* deinit jpeg buffer if allocated */ 981 if(mJpegHeap != NULL) mJpegHeap.clear(); 982 mJpegHeap = NULL; 983 984 /* memset some global structure */ 985 memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf)); 986 memset(&mPostviewStreamBuf, 0, sizeof(mPostviewStreamBuf)); 987 mSnapshotQueue.flush(); 988 mWDNQueue.flush(); 989 990 setSnapshotState(SNAPSHOT_STATE_UNINIT); 991 992 ALOGV("%s: X", __func__); 993 } 994 995 /*Temp: to be removed once event handling is enabled in mm-camera. 996 We need an event - one event for 997 stream-off to disable OPS_SNAPSHOT*/ 998 void QCameraStream_Snapshot::runSnapshotThread(void *data) 999 { 1000 ALOGV("%s: E", __func__); 1001 1002 if (mSnapshotFormat == PICTURE_FORMAT_RAW) { 1003 /* TBD: Temp: Needs to be removed once event handling is enabled. 1004 We cannot call mm-camera interface to stop snapshot from callback 1005 function as it causes deadlock. Hence handling it here temporarily 1006 in this thread. Later mm-camera intf will give us event in separate 1007 thread context */ 1008 mm_app_snapshot_wait(); 1009 /* Send command to stop snapshot polling thread*/ 1010 stop(); 1011 } 1012 ALOGV("%s: X", __func__); 1013 } 1014 1015 /*Temp: to be removed once event handling is enabled in mm-camera*/ 1016 static void *snapshot_thread(void *obj) 1017 { 1018 QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)obj; 1019 ALOGV("%s: E", __func__); 1020 if (pme != 0) { 1021 pme->runSnapshotThread(obj); 1022 } 1023 else ALOGW("not starting snapshot thread: the object went away!"); 1024 ALOGV("%s: X", __func__); 1025 return NULL; 1026 } 1027 1028 /*Temp: to be removed later*/ 1029 static pthread_t mSnapshotThread; 1030 1031 status_t QCameraStream_Snapshot::initJPEGSnapshot(int num_of_snapshots) 1032 { 1033 status_t ret = NO_ERROR; 1034 cam_ctrl_dimension_t dim; 1035 mm_camera_op_mode_type_t op_mode; 1036 1037 ALOGV("%s: E", __func__); 1038 1039 if (isFullSizeLiveshot()) 1040 goto end; 1041 1042 ALOGV("%s: Get current dimension", __func__); 1043 /* Query mm_camera to get current dimension */ 1044 memset(&dim, 0, sizeof(cam_ctrl_dimension_t)); 1045 ret = cam_config_get_parm(mCameraId, 1046 MM_CAMERA_PARM_DIMENSION, &dim); 1047 if (NO_ERROR != ret) { 1048 ALOGE("%s: error - can't get preview dimension!", __func__); 1049 ret = FAILED_TRANSACTION; 1050 goto end; 1051 } 1052 1053 /* Set camera op mode to MM_CAMERA_OP_MODE_CAPTURE */ 1054 ALOGV("Setting OP_MODE_CAPTURE"); 1055 op_mode = MM_CAMERA_OP_MODE_CAPTURE; 1056 if( NO_ERROR != cam_config_set_parm(mCameraId, 1057 MM_CAMERA_PARM_OP_MODE, &op_mode)) { 1058 ALOGE("%s: MM_CAMERA_OP_MODE_CAPTURE failed", __func__); 1059 ret = FAILED_TRANSACTION; 1060 goto end; 1061 } 1062 1063 /* config the parmeters and see if we need to re-init the stream*/ 1064 ALOGV("%s: Configure Snapshot Dimension", __func__); 1065 ret = configSnapshotDimension(&dim); 1066 if (ret != NO_ERROR) { 1067 ALOGE("%s: Setting snapshot dimension failed", __func__); 1068 goto end; 1069 } 1070 1071 /* Initialize stream - set format, acquire channel */ 1072 ret = initSnapshotFormat(&dim); 1073 if (NO_ERROR != ret) { 1074 ALOGE("%s: error - can't init nonZSL stream!", __func__); 1075 goto end; 1076 } 1077 1078 ret = initSnapshotBuffers(&dim, num_of_snapshots); 1079 if ( NO_ERROR != ret ){ 1080 ALOGE("%s: Failure allocating memory for Snapshot buffers", __func__); 1081 goto end; 1082 } 1083 1084 { 1085 /*register main and thumbnail buffers at back-end for frameproc*/ 1086 for (int i = 0; i < num_of_snapshots; i++) { 1087 if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i, 1088 mSnapshotStreamBuf.frame[i].fd, mHalCamCtrl->mSnapshotMemory.size, mCameraId, 1089 CAM_SOCK_MSG_TYPE_FD_MAPPING)) { 1090 ALOGE("%s: sending mapping data Msg Failed", __func__); 1091 } 1092 if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, i, 1093 mPostviewStreamBuf.frame[i].fd, mHalCamCtrl->mThumbnailMemory.size, mCameraId, 1094 CAM_SOCK_MSG_TYPE_FD_MAPPING)) { 1095 ALOGE("%s: sending mapping data Msg Failed", __func__); 1096 } 1097 } 1098 } 1099 1100 end: 1101 /* Based on what state we are in, we'll need to handle error - 1102 like deallocating memory if we have already allocated */ 1103 if (ret != NO_ERROR) { 1104 handleError(); 1105 } 1106 ALOGV("%s: X", __func__); 1107 return ret; 1108 1109 } 1110 1111 status_t QCameraStream_Snapshot::initRawSnapshot(int num_of_snapshots) 1112 { 1113 status_t ret = NO_ERROR; 1114 cam_ctrl_dimension_t dim; 1115 bool initSnapshot = false; 1116 mm_camera_op_mode_type_t op_mode; 1117 1118 ALOGV("%s: E", __func__); 1119 1120 /* Set camera op mode to MM_CAMERA_OP_MODE_CAPTURE */ 1121 ALOGV("%s: Setting OP_MODE_CAPTURE", __func__); 1122 op_mode = MM_CAMERA_OP_MODE_CAPTURE; 1123 if( NO_ERROR != cam_config_set_parm(mCameraId, 1124 MM_CAMERA_PARM_OP_MODE, &op_mode)) { 1125 ALOGE("%s: MM_CAMERA_OP_MODE_CAPTURE failed", __func__); 1126 ret = FAILED_TRANSACTION; 1127 goto end; 1128 } 1129 1130 /* For raw snapshot, we do not know the dimension as it 1131 depends on sensor to sensor. We call getDimension which will 1132 give us raw width and height */ 1133 memset(&dim, 0, sizeof(cam_ctrl_dimension_t)); 1134 ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim); 1135 if (MM_CAMERA_OK != ret) { 1136 ALOGE("%s: error - can't get dimension!", __func__); 1137 ALOGV("%s: X", __func__); 1138 goto end; 1139 } 1140 ALOGV("%s: Raw Snapshot dimension: %dx%d", __func__, 1141 dim.raw_picture_width, 1142 dim.raw_picture_height); 1143 1144 1145 ret = initRawSnapshotChannel(&dim, num_of_snapshots); 1146 if (NO_ERROR != ret) { 1147 ALOGE("%s: error - can't init nonZSL stream!", __func__); 1148 goto end; 1149 } 1150 1151 ret = initRawSnapshotBuffers(&dim, num_of_snapshots); 1152 if ( NO_ERROR != ret ){ 1153 ALOGE("%s: Failure allocating memory for Raw Snapshot buffers", 1154 __func__); 1155 goto end; 1156 } 1157 setSnapshotState(SNAPSHOT_STATE_INITIALIZED); 1158 1159 end: 1160 if (ret != NO_ERROR) { 1161 handleError(); 1162 } 1163 ALOGV("%s: X", __func__); 1164 return ret; 1165 } 1166 1167 status_t QCameraStream_Snapshot::initFullLiveshot(void) 1168 { 1169 status_t ret = NO_ERROR; 1170 cam_ctrl_dimension_t dim; 1171 bool matching = true; 1172 1173 memset(&dim, 0, sizeof(cam_ctrl_dimension_t)); 1174 ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim); 1175 if (MM_CAMERA_OK != ret) { 1176 ALOGE("%s: error - can't get dimension!", __func__); 1177 return ret; 1178 } 1179 #if 1 1180 /* First check if the picture resolution is the same, if not, change it*/ 1181 mHalCamCtrl->getPictureSize(&mPictureWidth, &mPictureHeight); 1182 ALOGV("%s: Picture size received: %d x %d", __func__, 1183 mPictureWidth, mPictureHeight); 1184 1185 //Use main image as input to encoder to generate thumbnail 1186 mThumbnailWidth = dim.picture_width; 1187 mThumbnailHeight = dim.picture_height; 1188 matching = (mPictureWidth == dim.picture_width) && 1189 (mPictureHeight == dim.picture_height); 1190 1191 //Actual thumbnail size requested 1192 mPostviewWidth = mHalCamCtrl->mParameters.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); 1193 mPostviewHeight = mHalCamCtrl->mParameters.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); 1194 1195 mDropThumbnail = false; 1196 if (mPostviewWidth == 0 && mPostviewHeight == 0) { 1197 mPostviewWidth = THUMBNAIL_DEFAULT_WIDTH; 1198 mPostviewHeight = THUMBNAIL_DEFAULT_HEIGHT; 1199 mDropThumbnail = true; 1200 } 1201 1202 if (!matching) { 1203 dim.picture_width = mPictureWidth; 1204 dim.picture_height = mPictureHeight; 1205 dim.ui_thumbnail_height = mThumbnailHeight; 1206 dim.ui_thumbnail_width = mThumbnailWidth; 1207 } 1208 ALOGV("%s: Picture size to set: %d x %d", __func__, 1209 dim.picture_width, dim.picture_height); 1210 ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim); 1211 #endif 1212 /* Initialize stream - set format, acquire channel */ 1213 ret = initSnapshotFormat(&dim); 1214 if (NO_ERROR != ret) { 1215 ALOGE("%s: error - can't init nonZSL stream!", __func__); 1216 return ret; 1217 } 1218 ret = initSnapshotBuffers(&dim, 1); 1219 if ( NO_ERROR != ret ){ 1220 ALOGE("%s: Failure allocating memory for Snapshot buffers", __func__); 1221 return ret; 1222 } 1223 1224 return ret; 1225 } 1226 1227 status_t QCameraStream_Snapshot::initZSLSnapshot(void) 1228 { 1229 status_t ret = NO_ERROR; 1230 cam_ctrl_dimension_t dim; 1231 mm_camera_op_mode_type_t op_mode; 1232 1233 ALOGV("%s: E", __func__); 1234 1235 ALOGV("%s: Get current dimension", __func__); 1236 /* Query mm_camera to get current dimension */ 1237 memset(&dim, 0, sizeof(cam_ctrl_dimension_t)); 1238 ret = cam_config_get_parm(mCameraId, 1239 MM_CAMERA_PARM_DIMENSION, &dim); 1240 if (NO_ERROR != ret) { 1241 ALOGE("%s: error - can't get preview dimension!", __func__); 1242 ret = FAILED_TRANSACTION; 1243 goto end; 1244 } 1245 1246 /* config the parmeters and see if we need to re-init the stream*/ 1247 ALOGV("%s: Configure Snapshot Dimension", __func__); 1248 ret = configSnapshotDimension(&dim); 1249 if (ret != NO_ERROR) { 1250 ALOGE("%s: Setting snapshot dimension failed", __func__); 1251 goto end; 1252 } 1253 1254 /* Initialize stream - set format, acquire channel */ 1255 ret = initSnapshotFormat(&dim); 1256 if (NO_ERROR != ret) { 1257 ALOGE("%s: error - can't init nonZSL stream!", __func__); 1258 goto end; 1259 } 1260 1261 /* For ZSL we'll have to allocate buffers for internal queue 1262 maintained by mm-camera lib plus around 3 buffers used for 1263 data handling by lower layer.*/ 1264 1265 ret = initSnapshotBuffers(&dim, mHalCamCtrl->getZSLQueueDepth() + 3); 1266 if ( NO_ERROR != ret ){ 1267 ALOGE("%s: Failure allocating memory for Snapshot buffers", __func__); 1268 goto end; 1269 } 1270 /*register main and thumbnail buffers at back-end for frameproc*/ 1271 for (int i = 0; i < mHalCamCtrl->getZSLQueueDepth() + 3; i++) { 1272 if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i, 1273 mSnapshotStreamBuf.frame[i].fd, mHalCamCtrl->mSnapshotMemory.size, mCameraId, 1274 CAM_SOCK_MSG_TYPE_FD_MAPPING)) { 1275 ALOGE("%s: sending mapping data Msg Failed", __func__); 1276 } 1277 } 1278 1279 end: 1280 /* Based on what state we are in, we'll need to handle error - 1281 like deallocating memory if we have already allocated */ 1282 if (ret != NO_ERROR) { 1283 handleError(); 1284 } 1285 ALOGV("%s: X", __func__); 1286 return ret; 1287 1288 } 1289 1290 status_t QCameraStream_Snapshot:: 1291 takePictureJPEG(void) 1292 { 1293 status_t ret = NO_ERROR; 1294 1295 ALOGV("%s: E", __func__); 1296 1297 if (mHalCamCtrl->mHdrMode == HDR_MODE) { 1298 hdrRawCount = 0; 1299 hdrJpegCount = 0; 1300 } 1301 /* Take snapshot */ 1302 ALOGV("%s: Call MM_CAMERA_OPS_SNAPSHOT", __func__); 1303 if (NO_ERROR != cam_ops_action(mCameraId, 1304 true, 1305 MM_CAMERA_OPS_SNAPSHOT, 1306 this)) { 1307 ALOGE("%s: Failure taking snapshot", __func__); 1308 ret = FAILED_TRANSACTION; 1309 goto end; 1310 } 1311 1312 /* TBD: Temp: to be removed once event callback 1313 is implemented in mm-camera lib */ 1314 pthread_attr_t attr; 1315 pthread_attr_init(&attr); 1316 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 1317 pthread_create(&mSnapshotThread,&attr, 1318 snapshot_thread, (void *)this); 1319 1320 end: 1321 if (ret != NO_ERROR) { 1322 handleError(); 1323 } 1324 1325 ALOGV("%s: X", __func__); 1326 return ret; 1327 1328 } 1329 1330 status_t QCameraStream_Snapshot:: 1331 takePictureRaw(void) 1332 { 1333 status_t ret = NO_ERROR; 1334 1335 ALOGV("%s: E", __func__); 1336 1337 /* Take snapshot */ 1338 ALOGV("%s: Call MM_CAMERA_OPS_SNAPSHOT", __func__); 1339 if (NO_ERROR != cam_ops_action(mCameraId, 1340 true, 1341 MM_CAMERA_OPS_RAW, 1342 this)) { 1343 ALOGE("%s: Failure taking snapshot", __func__); 1344 ret = FAILED_TRANSACTION; 1345 goto end; 1346 } 1347 1348 /* TBD: Temp: to be removed once event callback 1349 is implemented in mm-camera lib */ 1350 /* Wait for snapshot frame callback to return*/ 1351 pthread_attr_t attr; 1352 pthread_attr_init(&attr); 1353 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 1354 pthread_create(&mSnapshotThread,&attr, 1355 snapshot_thread, (void *)this); 1356 1357 end: 1358 if (ret != NO_ERROR) { 1359 handleError(); 1360 } 1361 ALOGV("%s: X", __func__); 1362 return ret; 1363 1364 } 1365 1366 status_t QCameraStream_Snapshot:: 1367 takePictureLiveshot(mm_camera_ch_data_buf_t* recvd_frame) 1368 { 1369 status_t ret = NO_ERROR; 1370 int mJpegMaxSize; 1371 int mNuberOfVFEOutputs = 0; 1372 common_crop_t crop_info; 1373 camera_notify_callback notifyCb; 1374 camera_data_callback dataCb; 1375 cam_ctrl_dimension_t dim; 1376 1377 mStopCallbackLock.lock(); 1378 if (!mHalCamCtrl->mStateLiveshot) { 1379 ALOGE("%s: Picture Cancelled", __func__); 1380 mStopCallbackLock.unlock(); 1381 return FAILED_TRANSACTION; 1382 } 1383 1384 ret = cam_config_get_parm(mHalCamCtrl->mCameraId,MM_CAMERA_PARM_VFE_OUTPUT_ENABLE, 1385 &mNuberOfVFEOutputs); 1386 if (ret != MM_CAMERA_OK) { 1387 ALOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE failed"); 1388 cam_evt_buf_done(mHalCamCtrl->mCameraId, recvd_frame); 1389 mStopCallbackLock.unlock(); 1390 return FAILED_TRANSACTION; 1391 } 1392 1393 mm_camera_ch_data_buf_t* frame = 1394 (mm_camera_ch_data_buf_t *)malloc(sizeof(mm_camera_ch_data_buf_t)); 1395 if (frame == NULL) { 1396 ALOGE("%s: Error allocating memory to save received_frame structure.", __func__); 1397 cam_evt_buf_done(mHalCamCtrl->mCameraId, recvd_frame); 1398 mStopCallbackLock.unlock(); 1399 return FAILED_TRANSACTION; 1400 } 1401 memcpy(frame, recvd_frame, sizeof(mm_camera_ch_data_buf_t)); 1402 1403 if (mNuberOfVFEOutputs == 1){ 1404 ALOGV("<DEBUG> Liveshot buffer idx:%d",frame->def.idx); 1405 frame->snapshot.main.frame = frame->def.frame; 1406 frame->snapshot.main.idx = frame->def.idx; 1407 frame->snapshot.thumbnail.frame = frame->def.frame; 1408 frame->snapshot.thumbnail.idx = frame->def.idx; 1409 } else { 1410 ALOGV("<DEBUG> Liveshot buffer idx:%d",frame->video.video.idx); 1411 frame->snapshot.main.frame = frame->video.video.frame; 1412 frame->snapshot.main.idx = frame->video.video.idx; 1413 frame->snapshot.thumbnail.frame = frame->video.video.frame; 1414 frame->snapshot.thumbnail.idx = frame->video.video.idx; 1415 } 1416 1417 memset(&dim, 0, sizeof(cam_ctrl_dimension_t)); 1418 ret = cam_config_get_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, &dim); 1419 if (MM_CAMERA_OK != ret) { 1420 ALOGE("%s: X error - can't get dimension!", __func__); 1421 cam_evt_buf_done(mHalCamCtrl->mCameraId, recvd_frame); 1422 setModeLiveSnapshot(false); 1423 mStopCallbackLock.unlock(); 1424 return FAILED_TRANSACTION; 1425 } 1426 dim.picture_width = dim.video_width; 1427 dim.picture_height = dim.video_height; 1428 dim.ui_thumbnail_width = dim.video_width; 1429 dim.ui_thumbnail_height = dim.video_height; 1430 1431 if (mNuberOfVFEOutputs == 1){ 1432 dim.main_img_format = dim.prev_format; 1433 dim.thumb_format = dim.prev_format; 1434 } else { 1435 dim.main_img_format = dim.enc_format; 1436 dim.thumb_format = dim.enc_format; 1437 } 1438 initSnapshotBuffers(&dim,1); 1439 1440 /* set flag to indicate we are doing livesnapshot */ 1441 resetSnapshotCounters( ); 1442 setModeLiveSnapshot(true); 1443 1444 mStopCallbackLock.unlock(); 1445 if (mHalCamCtrl->mStateLiveshot) { 1446 if(!mHalCamCtrl->mShutterSoundPlayed) { 1447 notifyShutter(&crop_info, true); 1448 } 1449 notifyShutter(&crop_info, false); 1450 mHalCamCtrl->mShutterSoundPlayed = false; 1451 } 1452 mStopCallbackLock.lock(); 1453 1454 // send upperlayer callback for raw image (data or notify, not both) 1455 if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){ 1456 dataCb = mHalCamCtrl->mDataCb; 1457 } else { 1458 dataCb = NULL; 1459 } 1460 if((mHalCamCtrl->mNotifyCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)){ 1461 notifyCb = mHalCamCtrl->mNotifyCb; 1462 } else { 1463 notifyCb = NULL; 1464 } 1465 1466 mPictureWidth = dim.picture_width; 1467 mPictureHeight = dim.picture_height; 1468 mThumbnailWidth = dim.ui_thumbnail_width; 1469 mThumbnailHeight = dim.ui_thumbnail_height; 1470 mPictureFormat = dim.main_img_format; 1471 mThumbnailFormat = dim.thumb_format; 1472 1473 mJpegMaxSize = mPictureWidth * mPictureHeight * 1.5; 1474 1475 ALOGV("Liveshot res = %d X %d, Thumabnail = %d % %d", 1476 mPictureWidth,mPictureHeight,mThumbnailWidth,mThumbnailHeight); 1477 1478 memset(&crop_info, 0, sizeof(common_crop_t)); 1479 crop_info.in1_w = mPictureWidth; 1480 crop_info.in1_h = mPictureHeight; 1481 /* For low power live snapshot the thumbnail output size is set to default size. 1482 In case of live snapshot video buffer = thumbnail buffer. For higher resolutions 1483 the thumnail will be dropped if its more than 64KB. To avoid thumbnail drop 1484 set thumbnail as configured by application. This will be a size lower than video size*/ 1485 mDropThumbnail = false; 1486 if(mHalCamCtrl->thumbnailWidth == 0 && mHalCamCtrl->thumbnailHeight == 0) { 1487 ALOGE("Live Snapshot thumbnail will be dropped as indicated by application"); 1488 mDropThumbnail = true; 1489 } 1490 crop_info.out1_w = mHalCamCtrl->thumbnailWidth; 1491 crop_info.out1_h = mHalCamCtrl->thumbnailHeight; 1492 ret = encodeData(frame, &crop_info, mJpegMaxSize, 0); 1493 if (ret != NO_ERROR) { 1494 ALOGE("%s: Failure configuring JPEG encoder", __func__); 1495 setModeLiveSnapshot(false); 1496 mStopCallbackLock.unlock(); 1497 ret = FAILED_TRANSACTION; 1498 goto end; 1499 } 1500 mStopCallbackLock.unlock(); 1501 if (dataCb && mHalCamCtrl->mStateLiveshot) { 1502 dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mRecordingMemory.camera_memory[frame->video.video.idx], 1503 1, NULL, mHalCamCtrl->mCallbackCookie); 1504 } 1505 if (notifyCb && mHalCamCtrl->mStateLiveshot) { 1506 notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie); 1507 } 1508 end: 1509 ALOGV("%s: X", __func__); 1510 return ret; 1511 } 1512 1513 status_t QCameraStream_Snapshot:: 1514 takePictureZSL(void) 1515 { 1516 status_t ret = NO_ERROR; 1517 mm_camera_ops_parm_get_buffered_frame_t param; 1518 1519 ALOGV("%s: E", __func__); 1520 1521 memset(¶m, 0, sizeof(param)); 1522 param.ch_type = MM_CAMERA_CH_SNAPSHOT; 1523 1524 /* Take snapshot */ 1525 ALOGV("%s: Call MM_CAMERA_OPS_GET_BUFFERED_FRAME", __func__); 1526 1527 mNumOfSnapshot = mHalCamCtrl->getNumOfSnapshots(); 1528 // it's just for stabilization for dequeuing zsl buffer frame 1529 // 13.2 ~ 22.4fps 1530 usleep(80000); 1531 if (NO_ERROR != cam_ops_action(mCameraId, 1532 true, 1533 MM_CAMERA_OPS_GET_BUFFERED_FRAME, 1534 ¶m)) { 1535 ALOGE("%s: Failure getting zsl frame(s)", __func__); 1536 ret = FAILED_TRANSACTION; 1537 goto end; 1538 } 1539 1540 /* TBD: Temp: to be removed once event callback 1541 is implemented in mm-camera lib */ 1542 /* pthread_attr_t attr; 1543 pthread_attr_init(&attr); 1544 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 1545 pthread_create(&mSnapshotThread,&attr, 1546 snapshot_thread, (void *)this); 1547 */ 1548 end: 1549 ALOGV("%s: X", __func__); 1550 return ret; 1551 } 1552 1553 status_t QCameraStream_Snapshot:: 1554 startStreamZSL(void) 1555 { 1556 status_t ret = NO_ERROR; 1557 1558 ALOGV("%s: E", __func__); 1559 1560 /* Start ZSL - it'll start queuing the frames */ 1561 ALOGV("%s: Call MM_CAMERA_OPS_ZSL", __func__); 1562 if (NO_ERROR != cam_ops_action(mCameraId, 1563 true, 1564 MM_CAMERA_OPS_ZSL, 1565 this)) { 1566 ALOGE("%s: Failure starting ZSL stream", __func__); 1567 ret = FAILED_TRANSACTION; 1568 goto end; 1569 } 1570 1571 end: 1572 ALOGV("%s: X", __func__); 1573 return ret; 1574 1575 } 1576 1577 status_t QCameraStream_Snapshot:: 1578 encodeData(mm_camera_ch_data_buf_t* recvd_frame, 1579 common_crop_t *crop_info, 1580 int frame_len, 1581 bool enqueued) 1582 { 1583 status_t ret = NO_ERROR; 1584 cam_ctrl_dimension_t dimension; 1585 struct msm_frame *postviewframe; 1586 struct msm_frame *mainframe; 1587 common_crop_t crop; 1588 cam_point_t main_crop_offset; 1589 cam_point_t thumb_crop_offset; 1590 int width, height; 1591 uint8_t *thumbnail_buf; 1592 uint32_t thumbnail_fd; 1593 uint8_t hw_encode = true; 1594 int mNuberOfVFEOutputs = 0; 1595 1596 omx_jpeg_encode_params encode_params; 1597 1598 /* If it's the only frame, we directly pass to encoder. 1599 If not, we'll queue it and check during next jpeg . 1600 Also, if the queue isn't empty then we need to queue this 1601 one too till its turn comes (only if it's not already 1602 queued up there)*/ 1603 ALOGV("%s: getSnapshotState()=%d, enqueued =%d, Q empty=%d", __func__, getSnapshotState(), enqueued, mSnapshotQueue.isEmpty()); 1604 ALOGV("%s: mNumOfRecievedJPEG=%d, mNumOfSnapshot =%d", __func__, mNumOfRecievedJPEG, mNumOfSnapshot); 1605 if(mHalCamCtrl->thumbnailWidth == 0 || mHalCamCtrl->thumbnailHeight == 0) { 1606 ALOGV("Snapshot thumbnail will be dropped as indicated by application"); 1607 mDropThumbnail = true; 1608 } 1609 if((getSnapshotState() == SNAPSHOT_STATE_JPEG_ENCODING) || 1610 (!mSnapshotQueue.isEmpty() && !enqueued)){ /*busy and new buffer*/ 1611 /* encoding is going on. Just queue the frame for now.*/ 1612 ALOGV("%s: JPEG encoding in progress." 1613 "Enqueuing frame id(%d) for later processing.", __func__, 1614 recvd_frame->snapshot.main.idx); 1615 mSnapshotQueue.enqueue((void *)recvd_frame); 1616 } else if (enqueued || 1617 (mNumOfRecievedJPEG != mNumOfSnapshot && mNumOfRecievedJPEG != 0)) { /*not busy, not first*/ 1618 ALOGV("%s: JPG not busy, not first frame.", __func__); 1619 1620 // For full-size live shot, use mainimage to generate thumbnail 1621 if (isFullSizeLiveshot()) { 1622 postviewframe = recvd_frame->snapshot.main.frame; 1623 } else { 1624 postviewframe = recvd_frame->snapshot.thumbnail.frame; 1625 } 1626 mainframe = recvd_frame->snapshot.main.frame; 1627 cam_config_get_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, &dimension); 1628 ALOGV("%s: main_fmt =%d, tb_fmt =%d", __func__, dimension.main_img_format, dimension.thumb_format); 1629 /*since this is the continue job, we only care about the input buffer*/ 1630 encode_params.thumbnail_buf = (uint8_t *)postviewframe->buffer; 1631 encode_params.thumbnail_fd = postviewframe->fd; 1632 encode_params.snapshot_buf = (uint8_t *)mainframe->buffer; 1633 encode_params.snapshot_fd = mainframe->fd; 1634 encode_params.dimension = &dimension; 1635 /*update exif parameters in HAL*/ 1636 mHalCamCtrl->setExifTags(); 1637 1638 encode_params.exif_data = mHalCamCtrl->getExifData(); 1639 encode_params.exif_numEntries = mHalCamCtrl->getExifTableNumEntries(); 1640 if (!omxJpegEncodeNext(&encode_params)){ 1641 ALOGE("%s: Failure! JPEG encoder returned error.", __func__); 1642 ret = FAILED_TRANSACTION; 1643 goto end; 1644 } 1645 /* Save the pointer to the frame sent for encoding. we'll need it to 1646 tell kernel that we are done with the frame.*/ 1647 mCurrentFrameEncoded = recvd_frame; 1648 setSnapshotState(SNAPSHOT_STATE_JPEG_ENCODING); 1649 } else { /*not busy and new buffer (first job)*/ 1650 1651 ALOGV("%s: JPG Idle and first frame.", __func__); 1652 1653 // For full-size live shot, use mainimage to generate thumbnail 1654 if (isFullSizeLiveshot()){ 1655 postviewframe = recvd_frame->snapshot.main.frame; 1656 } else { 1657 postviewframe = recvd_frame->snapshot.thumbnail.frame; 1658 } 1659 mainframe = recvd_frame->snapshot.main.frame; 1660 cam_config_get_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, &dimension); 1661 ALOGV("%s: main_fmt =%d, tb_fmt =%d", __func__, dimension.main_img_format, dimension.thumb_format); 1662 1663 dimension.orig_picture_dx = mPictureWidth; 1664 dimension.orig_picture_dy = mPictureHeight; 1665 1666 if(!mDropThumbnail) { 1667 if(isZSLMode()) { 1668 ALOGV("Setting input thumbnail size to previewWidth= %d previewheight= %d in ZSL mode", 1669 mHalCamCtrl->mPreviewWidth, mHalCamCtrl->mPreviewHeight); 1670 dimension.thumbnail_width = width = mHalCamCtrl->mPreviewWidth; 1671 dimension.thumbnail_height = height = mHalCamCtrl->mPreviewHeight; 1672 } else { 1673 dimension.thumbnail_width = width = mThumbnailWidth; 1674 dimension.thumbnail_height = height = mThumbnailHeight; 1675 } 1676 } else { 1677 dimension.thumbnail_width = width = 0; 1678 dimension.thumbnail_height = height = 0; 1679 } 1680 dimension.main_img_format = mPictureFormat; 1681 dimension.thumb_format = mThumbnailFormat; 1682 1683 /*TBD: Move JPEG handling to the mm-camera library */ 1684 ALOGV("Setting callbacks, initializing encoder and start encoding."); 1685 ALOGV(" Passing my obj: %x", (unsigned int) this); 1686 set_callbacks(snapshot_jpeg_fragment_cb, snapshot_jpeg_cb, this, 1687 mHalCamCtrl->mJpegMemory.camera_memory[0]->data, &mJpegOffset); 1688 1689 if (isLiveSnapshot() || isFullSizeLiveshot()) { 1690 /* determine the target type */ 1691 ret = cam_config_get_parm(mCameraId,MM_CAMERA_PARM_VFE_OUTPUT_ENABLE, 1692 &mNuberOfVFEOutputs); 1693 if (ret != MM_CAMERA_OK) { 1694 ALOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE failed"); 1695 ret = BAD_VALUE; 1696 } 1697 /* VFE 2x has hardware limitation: 1698 * It can't support concurrent 1699 * video encoding and jpeg encoding 1700 * So switch to software for liveshot 1701 */ 1702 if (mNuberOfVFEOutputs == 1) 1703 hw_encode = false; 1704 } 1705 ALOGV("%s: hw_encode: %d\n",__func__, hw_encode); 1706 1707 if(omxJpegStart(hw_encode) != NO_ERROR){ 1708 ALOGE("Error In omxJpegStart!!! Return"); 1709 ret = FAILED_TRANSACTION; 1710 goto end; 1711 } 1712 1713 if (mHalCamCtrl->getJpegQuality()) 1714 mm_jpeg_encoder_setMainImageQuality(mHalCamCtrl->getJpegQuality()); 1715 else 1716 mm_jpeg_encoder_setMainImageQuality(85); 1717 1718 ALOGV("%s: Dimension to encode: main: %dx%d thumbnail: %dx%d", __func__, 1719 dimension.orig_picture_dx, dimension.orig_picture_dy, 1720 dimension.thumbnail_width, dimension.thumbnail_height); 1721 1722 /*TBD: Pass 0 as cropinfo for now as v4l2 doesn't provide 1723 cropinfo. It'll be changed later.*/ 1724 memset(&crop,0,sizeof(common_crop_t)); 1725 memset(&main_crop_offset,0,sizeof(cam_point_t)); 1726 memset(&thumb_crop_offset,0,sizeof(cam_point_t)); 1727 1728 /* Setting crop info */ 1729 1730 /*Main image*/ 1731 crop.in2_w=mCrop.snapshot.main_crop.width;// dimension.picture_width 1732 crop.in2_h=mCrop.snapshot.main_crop.height;// dimension.picture_height; 1733 if (!mJpegDownscaling) { 1734 crop.out2_w = mPictureWidth; 1735 crop.out2_h = mPictureHeight; 1736 } else { 1737 crop.out2_w = mActualPictureWidth; 1738 crop.out2_h = mActualPictureHeight; 1739 if (!crop.in2_w || !crop.in2_h) { 1740 crop.in2_w = mPictureWidth; 1741 crop.in2_h = mPictureHeight; 1742 } 1743 } 1744 main_crop_offset.x=mCrop.snapshot.main_crop.left; 1745 main_crop_offset.y=mCrop.snapshot.main_crop.top; 1746 /*Thumbnail image*/ 1747 crop.in1_w=mCrop.snapshot.thumbnail_crop.width; //dimension.thumbnail_width; 1748 crop.in1_h=mCrop.snapshot.thumbnail_crop.height; // dimension.thumbnail_height; 1749 if(isLiveSnapshot() || isFullSizeLiveshot() || isZSLMode()) { 1750 crop.out1_w= mHalCamCtrl->thumbnailWidth; 1751 crop.out1_h= mHalCamCtrl->thumbnailHeight; 1752 ALOGV("Thumbnail width= %d height= %d for livesnapshot", crop.out1_w, crop.out1_h); 1753 } else { 1754 crop.out1_w = width; 1755 crop.out1_h = height; 1756 } 1757 thumb_crop_offset.x=mCrop.snapshot.thumbnail_crop.left; 1758 thumb_crop_offset.y=mCrop.snapshot.thumbnail_crop.top; 1759 1760 if (crop.out1_w > crop.out2_w || crop.out1_h > crop.out2_h) { 1761 crop.out1_w = crop.out2_w; 1762 crop.out1_h = crop.out2_h; 1763 } 1764 //update exif parameters in HAL 1765 mHalCamCtrl->initExifData(); 1766 1767 /*Fill in the encode parameters*/ 1768 encode_params.dimension = (const cam_ctrl_dimension_t *)&dimension; 1769 //if (!isFullSizeLiveshot()) { 1770 encode_params.thumbnail_buf = (uint8_t *)postviewframe->buffer; 1771 encode_params.thumbnail_fd = postviewframe->fd; 1772 encode_params.thumbnail_offset = postviewframe->phy_offset; 1773 encode_params.thumb_crop_offset = &thumb_crop_offset; 1774 //} 1775 encode_params.snapshot_buf = (uint8_t *)mainframe->buffer; 1776 encode_params.snapshot_fd = mainframe->fd; 1777 encode_params.snapshot_offset = mainframe->phy_offset; 1778 encode_params.scaling_params = &crop; 1779 encode_params.exif_data = mHalCamCtrl->getExifData(); 1780 encode_params.exif_numEntries = mHalCamCtrl->getExifTableNumEntries(); 1781 1782 if (isLiveSnapshot() && !isFullSizeLiveshot()) 1783 encode_params.a_cbcroffset = mainframe->cbcr_off; 1784 else 1785 encode_params.a_cbcroffset = -1; 1786 encode_params.main_crop_offset = &main_crop_offset; 1787 1788 if (mDropThumbnail) 1789 encode_params.hasThumbnail = 0; 1790 else 1791 encode_params.hasThumbnail = 1; 1792 encode_params.thumb_crop_offset = &thumb_crop_offset; 1793 encode_params.main_format = dimension.main_img_format; 1794 encode_params.thumbnail_format = dimension.thumb_format; 1795 1796 if (!omxJpegEncode(&encode_params)){ 1797 ALOGE("%s: Failure! JPEG encoder returned error.", __func__); 1798 ret = FAILED_TRANSACTION; 1799 goto end; 1800 } 1801 1802 /* Save the pointer to the frame sent for encoding. we'll need it to 1803 tell kernel that we are done with the frame.*/ 1804 mCurrentFrameEncoded = recvd_frame; 1805 setSnapshotState(SNAPSHOT_STATE_JPEG_ENCODING); 1806 } 1807 1808 end: 1809 ALOGV("%s: X", __func__); 1810 return ret; 1811 } 1812 1813 /* Called twice - 1st to play shutter sound and 2nd to configure 1814 overlay/surfaceflinger for postview */ 1815 void QCameraStream_Snapshot::notifyShutter(common_crop_t *crop, 1816 bool mPlayShutterSoundOnly) 1817 { 1818 ALOGV("%s: E", __func__); 1819 if(!mActive && !isLiveSnapshot()) { 1820 ALOGE("__debbug: Snapshot thread stopped \n"); 1821 return; 1822 } 1823 if(mHalCamCtrl->mNotifyCb) 1824 mHalCamCtrl->mNotifyCb(CAMERA_MSG_SHUTTER, 0, mPlayShutterSoundOnly, 1825 mHalCamCtrl->mCallbackCookie); 1826 ALOGV("%s: X", __func__); 1827 } 1828 1829 status_t QCameraStream_Snapshot:: 1830 encodeDisplayAndSave(mm_camera_ch_data_buf_t* recvd_frame, 1831 bool enqueued) 1832 { 1833 status_t ret = NO_ERROR; 1834 struct msm_frame *postview_frame; 1835 struct ion_flush_data cache_inv_data; 1836 int ion_fd; 1837 int buf_index = 0; 1838 ssize_t offset_addr = 0; 1839 common_crop_t dummy_crop; 1840 /* send frame for encoding */ 1841 ALOGV("%s: Send frame for encoding", __func__); 1842 /*TBD: Pass 0 as cropinfo for now as v4l2 doesn't provide 1843 cropinfo. It'll be changed later.*/ 1844 if(!mActive) { 1845 ALOGE("Cancel Picture.. Stop is called"); 1846 return NO_ERROR; 1847 } 1848 if(isZSLMode()){ 1849 ALOGV("%s: set JPEG rotation in ZSL mode", __func__); 1850 mHalCamCtrl->setJpegRotation(isZSLMode()); 1851 } 1852 #ifdef USE_ION 1853 /*Clean out(Write-back) cache before sending for JPEG*/ 1854 memset(&cache_inv_data, 0, sizeof(struct ion_flush_data)); 1855 cache_inv_data.vaddr = (void*)recvd_frame->snapshot.main.frame->buffer; 1856 cache_inv_data.fd = recvd_frame->snapshot.main.frame->fd; 1857 cache_inv_data.handle = recvd_frame->snapshot.main.frame->fd_data.handle; 1858 cache_inv_data.length = recvd_frame->snapshot.main.frame->ion_alloc.len; 1859 ion_fd = recvd_frame->snapshot.main.frame->ion_dev_fd; 1860 if(ion_fd > 0) { 1861 if(mHalCamCtrl->cache_ops(ion_fd, &cache_inv_data, ION_IOC_CLEAN_INV_CACHES) < 0) 1862 ALOGE("%s: Cache Invalidate failed\n", __func__); 1863 else { 1864 ALOGV("%s: Successful cache invalidate\n", __func__); 1865 if(!isFullSizeLiveshot()) { 1866 ion_fd = recvd_frame->snapshot.thumbnail.frame->ion_dev_fd; 1867 cache_inv_data.vaddr = (void*)recvd_frame->snapshot.thumbnail.frame->buffer; 1868 cache_inv_data.fd = recvd_frame->snapshot.thumbnail.frame->fd; 1869 cache_inv_data.handle = recvd_frame->snapshot.thumbnail.frame->fd_data.handle; 1870 cache_inv_data.length = recvd_frame->snapshot.thumbnail.frame->ion_alloc.len; 1871 if(mHalCamCtrl->cache_ops(ion_fd, &cache_inv_data, ION_IOC_CLEAN_INV_CACHES) < 0) 1872 ALOGE("%s: Cache Invalidate failed\n", __func__); 1873 else 1874 ALOGV("%s: Successful cache invalidate\n", __func__); 1875 } 1876 } 1877 } 1878 #endif 1879 memset(&dummy_crop,0,sizeof(common_crop_t)); 1880 ret = encodeData(recvd_frame, &dummy_crop, mSnapshotStreamBuf.frame_len, 1881 enqueued); 1882 if (ret != NO_ERROR) { 1883 ALOGE("%s: Failure configuring JPEG encoder", __func__); 1884 1885 goto end; 1886 } 1887 1888 /* Display postview image*/ 1889 /* If it's burst mode, we won't be displaying postview of all the captured 1890 images - only the first one */ 1891 ALOGV("%s: Burst mode flag %d", __func__, mBurstModeFlag); 1892 1893 end: 1894 ALOGV("%s: X", __func__); 1895 return ret; 1896 } 1897 1898 status_t QCameraStream_Snapshot::receiveRawPicture(mm_camera_ch_data_buf_t* recvd_frame) 1899 { 1900 int buf_index = 0; 1901 common_crop_t crop; 1902 int rc = NO_ERROR; 1903 int cur_lux_idx = 0; 1904 1905 camera_notify_callback notifyCb; 1906 camera_data_callback dataCb, jpgDataCb; 1907 1908 ALOGV("%s: E ", __func__); 1909 mStopCallbackLock.lock( ); 1910 if(!mActive) { 1911 mStopCallbackLock.unlock(); 1912 ALOGV("%s: Stop receiving raw pic ", __func__); 1913 return NO_ERROR; 1914 } 1915 1916 if(getSnapshotState() == SNAPSHOT_STATE_ERROR) { 1917 cam_evt_buf_done(mCameraId, recvd_frame); 1918 } 1919 1920 mHalCamCtrl->dumpFrameToFile(recvd_frame->snapshot.main.frame, HAL_DUMP_FRM_MAIN); 1921 if (!isFullSizeLiveshot()) 1922 mHalCamCtrl->dumpFrameToFile(recvd_frame->snapshot.thumbnail.frame, 1923 HAL_DUMP_FRM_THUMBNAIL); 1924 1925 /* If it's raw snapshot, we just want to tell upperlayer to save the image*/ 1926 if(mSnapshotFormat == PICTURE_FORMAT_RAW) { 1927 ALOGV("%s: Call notifyShutter 2nd time in case of RAW", __func__); 1928 mStopCallbackLock.unlock(); 1929 if(!mHalCamCtrl->mShutterSoundPlayed) { 1930 notifyShutter(&crop, true); 1931 } 1932 notifyShutter(&crop, false); 1933 mHalCamCtrl->mShutterSoundPlayed = false; 1934 1935 mStopCallbackLock.lock( ); 1936 ALOGV("%s: Sending Raw Snapshot Callback to Upperlayer", __func__); 1937 buf_index = recvd_frame->def.idx; 1938 1939 if (mHalCamCtrl->mDataCb && mActive && 1940 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)){ 1941 dataCb = mHalCamCtrl->mDataCb; 1942 } else { 1943 dataCb = NULL; 1944 } 1945 mStopCallbackLock.unlock(); 1946 1947 if(dataCb) { 1948 dataCb( 1949 CAMERA_MSG_COMPRESSED_IMAGE, 1950 mHalCamCtrl->mRawMemory.camera_memory[buf_index], 0, NULL, 1951 mHalCamCtrl->mCallbackCookie); 1952 } 1953 /* TBD: Temp: To be removed once event handling is enabled */ 1954 mm_app_snapshot_done(); 1955 } else { 1956 /*TBD: v4l2 doesn't have support to provide cropinfo along with 1957 frame. We'll need to query.*/ 1958 memset(&crop, 0, sizeof(common_crop_t)); 1959 1960 if(isZSLMode()){ 1961 //Changes to stop sending Preview Frames when Snapshot issued 1962 //in ZSL case. 1963 mHalCamCtrl->mPauseFramedispatch = true; 1964 } 1965 1966 ALOGV("%s: Call notifyShutter 2nd time", __func__); 1967 /* The recvd_frame structre we receive from lower library is a local 1968 variable. So we'll need to save this structure so that we won't 1969 be later pointing to garbage data when that variable goes out of 1970 scope */ 1971 mm_camera_ch_data_buf_t* frame = 1972 (mm_camera_ch_data_buf_t *)malloc(sizeof(mm_camera_ch_data_buf_t)); 1973 if (frame == NULL) { 1974 ALOGE("%s: Error allocating memory to save received_frame structure.", __func__); 1975 cam_evt_buf_done(mCameraId, recvd_frame); 1976 mStopCallbackLock.unlock(); 1977 return BAD_VALUE; 1978 } 1979 memcpy(frame, recvd_frame, sizeof(mm_camera_ch_data_buf_t)); 1980 rc = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_LUX_IDX, &cur_lux_idx); 1981 1982 if (cur_lux_idx > 370) { 1983 static int input_width = 0, input_height = 0; 1984 static int ret = 0; 1985 unsigned char *dnr_buffer; 1986 input_width = mPictureWidth; 1987 input_height = mPictureHeight; 1988 1989 ALOGV("%s: received frame %d * %d", __func__, input_width, input_height); 1990 { 1991 dnr_buffer = (uint8_t *)malloc(input_width*input_height*3/2); 1992 if (dnr_buffer == NULL) 1993 ALOGE("dnr_buffer alloc fail"); 1994 ALOGV("dnr_buffer allocated size : %d", input_width*input_height*3/2); 1995 memcpy(dnr_buffer, (uint8_t *)frame->snapshot.main.frame->buffer, input_width*input_height*3/2); 1996 ALOGV("dnr_buffer memcpy completed."); 1997 } 1998 ALOGV("[DNR] DNR Processing Start.... %d * %d\n", mPictureWidth, mPictureHeight); 1999 ret = NO_ERROR; 2000 if (mHalCamCtrl->LINK_morpho_DNR_ProcessFrame) 2001 ret = (int)mHalCamCtrl->LINK_morpho_DNR_ProcessFrame(dnr_buffer, mPictureWidth, mPictureHeight, 1, 1); //bright->normal->dark 2002 ALOGV("[DNR] DNR Processing result.... ret = %d\n", ret); 2003 memcpy((uint8_t *)recvd_frame->snapshot.main.frame->buffer, (uint8_t *)dnr_buffer, mPictureWidth*mPictureHeight*3/2); 2004 ALOGV("[DNR] DNR Processing END....\n"); 2005 if(dnr_buffer) 2006 free(dnr_buffer); 2007 } 2008 //mStopCallbackLock.lock(); 2009 2010 // only in ZSL mode and Wavelet Denoise is enabled, we will send frame to deamon to do WDN 2011 if (isZSLMode() && mHalCamCtrl->isWDenoiseEnabled()) { 2012 if(mIsDoingWDN){ 2013 mWDNQueue.enqueue((void *)frame); 2014 ALOGV("%s: Wavelet denoise is going on, queue frame", __func__); 2015 rc = NO_ERROR; 2016 } else { 2017 ALOGV("%s: Start Wavelet denoise", __func__); 2018 mIsDoingWDN = true; // set the falg to true because we are going to do WDN 2019 2020 // No WDN is going on so far, we will start it here 2021 rc = doWaveletDenoise(frame); 2022 if ( NO_ERROR != rc ) { 2023 ALOGE("%s: Error while doing wavelet denoise", __func__); 2024 mIsDoingWDN = false; 2025 } 2026 } 2027 } else if (mHdrInfo.hdr_on) { 2028 mHdrInfo.recvd_frame[mHdrInfo.num_raw_received] = frame; 2029 mHdrInfo.num_raw_received++; 2030 ALOGV("%s Total %d Received %d frames, still need to receive %d frames", __func__, 2031 mHdrInfo.num_frame, mHdrInfo.num_raw_received, (mHdrInfo.num_frame - mHdrInfo.num_raw_received)); 2032 if (mHdrInfo.num_raw_received == mHdrInfo.num_frame) { 2033 ALOGV(" Received all %d YUV frames, Invoke HDR", mHdrInfo.num_raw_received); 2034 doHdrProcessing(); 2035 } 2036 } 2037 else { 2038 ALOGV("%s: encodeDisplayAndSave ", __func__); 2039 rc = encodeDisplayAndSave(frame, 0); 2040 } 2041 2042 2043 // send upperlayer callback for raw image (data or notify, not both) 2044 if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){ 2045 dataCb = mHalCamCtrl->mDataCb; 2046 } else { 2047 dataCb = NULL; 2048 } 2049 if((mHalCamCtrl->mNotifyCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)){ 2050 notifyCb = mHalCamCtrl->mNotifyCb; 2051 } else { 2052 notifyCb = NULL; 2053 } 2054 2055 mStopCallbackLock.unlock(); 2056 if(!mHalCamCtrl->mShutterSoundPlayed) { 2057 notifyShutter(&crop, true); 2058 } 2059 notifyShutter(&crop, false); 2060 mHalCamCtrl->mShutterSoundPlayed = false; 2061 2062 if(mHalCamCtrl->mHdrMode == HDR_MODE) { 2063 if ((hdrRawCount % 3) != 2) 2064 return NO_ERROR; 2065 else 2066 hdrRawCount++; 2067 } 2068 2069 if (rc != NO_ERROR) 2070 { 2071 ALOGE("%s: Error while encoding/displaying/saving image", __func__); 2072 cam_evt_buf_done(mCameraId, recvd_frame); 2073 2074 if(mHalCamCtrl->mDataCb && 2075 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) { 2076 /* get picture failed. Give jpeg callback with NULL data 2077 * to the application to restore to preview mode 2078 */ 2079 jpgDataCb = mHalCamCtrl->mDataCb; 2080 } else { 2081 jpgDataCb = NULL; 2082 } 2083 ALOGE("%s: encode err so data cb", __func__); 2084 //mStopCallbackLock.unlock(); 2085 if (dataCb) { 2086 dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0], 2087 1, NULL, mHalCamCtrl->mCallbackCookie); 2088 } 2089 if (notifyCb) { 2090 notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie); 2091 } 2092 if (jpgDataCb) { 2093 jpgDataCb(CAMERA_MSG_COMPRESSED_IMAGE, 2094 NULL, 0, NULL, 2095 mHalCamCtrl->mCallbackCookie); 2096 } 2097 2098 if (frame != NULL) { 2099 free(frame); 2100 } 2101 } else { 2102 2103 //mStopCallbackLock.unlock(); 2104 if (dataCb) { 2105 dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0], 2106 1, NULL, mHalCamCtrl->mCallbackCookie); 2107 } 2108 if (notifyCb) { 2109 notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie); 2110 } 2111 2112 if (!isZSLMode() && 2113 (!isLiveSnapshot() && !isFullSizeLiveshot())) { 2114 if(mHalCamCtrl->mDataCb && 2115 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_POSTVIEW_FRAME)) { 2116 mHalCamCtrl->mDataCb(CAMERA_MSG_POSTVIEW_FRAME,mHalCamCtrl->mThumbnailMemory.camera_memory[0], 2117 0, NULL, mHalCamCtrl->mCallbackCookie); 2118 } 2119 } 2120 } 2121 } 2122 2123 ALOGV("%s: X", __func__); 2124 return NO_ERROR; 2125 } 2126 2127 //------------------------------------------------------------------- 2128 // Helper Functions 2129 //------------------------------------------------------------------- 2130 void QCameraStream_Snapshot::handleError() 2131 { 2132 mm_camera_channel_type_t ch_type; 2133 ALOGV("%s: E", __func__); 2134 2135 /* Depending upon the state we'll have to 2136 handle error */ 2137 switch(getSnapshotState()) { 2138 case SNAPSHOT_STATE_JPEG_ENCODING: 2139 if(mJpegHeap != NULL) mJpegHeap.clear(); 2140 mJpegHeap = NULL; 2141 2142 case SNAPSHOT_STATE_YUV_RECVD: 2143 case SNAPSHOT_STATE_IMAGE_CAPTURE_STRTD: 2144 stopPolling(); 2145 case SNAPSHOT_STATE_INITIALIZED: 2146 case SNAPSHOT_STATE_BUF_INITIALIZED: 2147 if (mSnapshotFormat == PICTURE_FORMAT_JPEG) { 2148 deinitSnapshotBuffers(); 2149 }else 2150 { 2151 deinitRawSnapshotBuffers(); 2152 } 2153 case SNAPSHOT_STATE_BUF_NOTIF_REGD: 2154 case SNAPSHOT_STATE_CH_ACQUIRED: 2155 if (mSnapshotFormat == PICTURE_FORMAT_JPEG) { 2156 deinitSnapshotChannel(MM_CAMERA_CH_SNAPSHOT); 2157 }else 2158 { 2159 deinitSnapshotChannel(MM_CAMERA_CH_RAW); 2160 } 2161 default: 2162 /* Set the state to ERROR */ 2163 setSnapshotState(SNAPSHOT_STATE_ERROR); 2164 break; 2165 } 2166 2167 ALOGV("%s: X", __func__); 2168 } 2169 2170 void QCameraStream_Snapshot::setSnapshotState(int state) 2171 { 2172 ALOGV("%s: Setting snapshot state to: %d", 2173 __func__, state); 2174 mSnapshotState = state; 2175 } 2176 2177 int QCameraStream_Snapshot::getSnapshotState() 2178 { 2179 return mSnapshotState; 2180 } 2181 2182 void QCameraStream_Snapshot::setModeLiveSnapshot(bool value) 2183 { 2184 mModeLiveSnapshot = value; 2185 } 2186 2187 bool QCameraStream_Snapshot::isLiveSnapshot(void) 2188 { 2189 return mModeLiveSnapshot; 2190 } 2191 bool QCameraStream_Snapshot::isZSLMode() 2192 { 2193 return (myMode & CAMERA_ZSL_MODE); 2194 } 2195 2196 void QCameraStream_Snapshot::setFullSizeLiveshot(bool value) 2197 { 2198 mFullLiveshot = value; 2199 } 2200 2201 bool QCameraStream_Snapshot::isFullSizeLiveshot() 2202 { 2203 return mFullLiveshot; 2204 } 2205 2206 void QCameraStream_Snapshot::resetSnapshotCounters(void ) 2207 { 2208 mNumOfSnapshot = mHalCamCtrl->getNumOfSnapshots(); 2209 if (mNumOfSnapshot <= 0) { 2210 mNumOfSnapshot = 1; 2211 } 2212 mNumOfRecievedJPEG = 0; 2213 ALOGV("%s: Number of images to be captured: %d", __func__, mNumOfSnapshot); 2214 } 2215 2216 //------------------------------------------------------------------ 2217 // Constructor and Destructor 2218 //------------------------------------------------------------------ 2219 QCameraStream_Snapshot:: 2220 QCameraStream_Snapshot(int cameraId, camera_mode_t mode) 2221 : QCameraStream(cameraId,mode), 2222 mSnapshotFormat(PICTURE_FORMAT_JPEG), 2223 mPictureWidth(0), mPictureHeight(0), 2224 mPictureFormat(CAMERA_YUV_420_NV21), 2225 mPostviewWidth(0), mPostviewHeight(0), 2226 mThumbnailWidth(0), mThumbnailHeight(0), 2227 mThumbnailFormat(CAMERA_YUV_420_NV21), 2228 mJpegOffset(0), 2229 mSnapshotState(SNAPSHOT_STATE_UNINIT), 2230 mNumOfSnapshot(1), 2231 mModeLiveSnapshot(false), 2232 mBurstModeFlag(false), 2233 mActualPictureWidth(0), 2234 mActualPictureHeight(0), 2235 mJpegDownscaling(false), 2236 mJpegHeap(NULL), 2237 mDisplayHeap(NULL), 2238 mPostviewHeap(NULL), 2239 mCurrentFrameEncoded(NULL), 2240 mJpegSessionId(0), 2241 mFullLiveshot(false), 2242 mDropThumbnail(false) 2243 { 2244 ALOGV("%s: E", __func__); 2245 2246 /*initialize snapshot queue*/ 2247 mSnapshotQueue.init(); 2248 memset (&mHdrInfo, 0, sizeof(snap_hdr_record_t )); 2249 2250 /*initialize WDN queue*/ 2251 mWDNQueue.init(); 2252 mIsDoingWDN = false; 2253 2254 memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf)); 2255 memset(&mPostviewStreamBuf, 0, sizeof(mPostviewStreamBuf)); 2256 mSnapshotBufferNum = 0; 2257 mMainSize = 0; 2258 mThumbSize = 0; 2259 for(int i = 0; i < mMaxSnapshotBufferCount; i++) { 2260 mMainfd[i] = 0; 2261 mThumbfd[i] = 0; 2262 mCameraMemoryPtrMain[i] = NULL; 2263 mCameraMemoryPtrThumb[i] = NULL; 2264 } 2265 /*load the jpeg lib*/ 2266 mJpegSessionId = omxJpegOpen( ); 2267 ALOGV("%s: X", __func__); 2268 } 2269 2270 2271 QCameraStream_Snapshot::~QCameraStream_Snapshot() { 2272 ALOGV("%s: E", __func__); 2273 2274 /* deinit snapshot queue */ 2275 if (mSnapshotQueue.isInitialized()) { 2276 mSnapshotQueue.deinit(); 2277 } 2278 /* deinit snapshot queue */ 2279 if (mWDNQueue.isInitialized()) { 2280 mWDNQueue.deinit(); 2281 } 2282 2283 if(mActive) { 2284 stop(); 2285 } 2286 if(mInit) { 2287 release(); 2288 } 2289 mInit = false; 2290 mActive = false; 2291 if (mJpegSessionId > 0) { 2292 omxJpegClose( ); 2293 mJpegSessionId = 0; 2294 } 2295 ALOGV("%s: X", __func__); 2296 2297 } 2298 2299 //------------------------------------------------------------------ 2300 // Public Members 2301 //------------------------------------------------------------------ 2302 status_t QCameraStream_Snapshot::init() 2303 { 2304 status_t ret = NO_ERROR; 2305 mm_camera_op_mode_type_t op_mode; 2306 2307 ALOGV("%s: E", __func__); 2308 /* Check the state. If we have already started snapshot 2309 process just return*/ 2310 if (getSnapshotState() != SNAPSHOT_STATE_UNINIT) { 2311 ret = isZSLMode() ? NO_ERROR : INVALID_OPERATION; 2312 ALOGE("%s: Trying to take picture while snapshot is in progress", 2313 __func__); 2314 goto end; 2315 } 2316 mInit = true; 2317 2318 end: 2319 /*if (ret == NO_ERROR) { 2320 setSnapshotState(SNAPSHOT_STATE_INITIALIZED); 2321 }*/ 2322 ALOGV("%s: X", __func__); 2323 return ret; 2324 } 2325 2326 status_t QCameraStream_Snapshot::start(void) { 2327 status_t ret = NO_ERROR; 2328 2329 ALOGV("%s: E", __func__); 2330 2331 Mutex::Autolock lock(mStopCallbackLock); 2332 2333 /* Keep track of number of snapshots to take - in case of 2334 multiple snapshot/burst mode */ 2335 2336 if(mHalCamCtrl->isRawSnapshot()) { 2337 ALOGV("%s: Acquire Raw Snapshot Channel", __func__); 2338 ret = cam_ops_ch_acquire(mCameraId, MM_CAMERA_CH_RAW); 2339 if (NO_ERROR != ret) { 2340 ALOGE("%s: Failure Acquiring Raw Snapshot Channel error =%d\n", 2341 __func__, ret); 2342 ret = FAILED_TRANSACTION; 2343 goto end; 2344 } 2345 /* Snapshot channel is acquired */ 2346 setSnapshotState(SNAPSHOT_STATE_CH_ACQUIRED); 2347 ALOGV("%s: Register buffer notification. My object: %x", 2348 __func__, (unsigned int) this); 2349 (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_RAW, 2350 snapshot_notify_cb, 2351 MM_CAMERA_REG_BUF_CB_INFINITE, 2352 0, 2353 this); 2354 /* Set the state to buffer notification completed */ 2355 setSnapshotState(SNAPSHOT_STATE_BUF_NOTIF_REGD); 2356 }else{ 2357 ALOGV("%s: Acquire Snapshot Channel", __func__); 2358 ret = cam_ops_ch_acquire(mCameraId, MM_CAMERA_CH_SNAPSHOT); 2359 if (NO_ERROR != ret) { 2360 ALOGE("%s: Failure Acquiring Snapshot Channel error =%d\n", __func__, ret); 2361 ret = FAILED_TRANSACTION; 2362 goto end; 2363 } 2364 /* Snapshot channel is acquired */ 2365 setSnapshotState(SNAPSHOT_STATE_CH_ACQUIRED); 2366 ALOGV("%s: Register buffer notification. My object: %x", 2367 __func__, (unsigned int) this); 2368 (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_SNAPSHOT, 2369 snapshot_notify_cb, 2370 MM_CAMERA_REG_BUF_CB_INFINITE, 2371 0, 2372 this); 2373 /* Set the state to buffer notification completed */ 2374 setSnapshotState(SNAPSHOT_STATE_BUF_NOTIF_REGD); 2375 } 2376 2377 if (isZSLMode()) { 2378 prepareHardware(); 2379 ret = initZSLSnapshot(); 2380 if(ret != NO_ERROR) { 2381 ALOGE("%s : Error while Initializing ZSL snapshot",__func__); 2382 goto end; 2383 } 2384 mHalCamCtrl->setExifTags(); 2385 /* In case of ZSL, start will only start snapshot stream and 2386 continuously queue the frames in a queue. When user clicks 2387 shutter we'll call get buffer from the queue and pass it on */ 2388 ret = startStreamZSL(); 2389 goto end; 2390 } 2391 2392 if (isFullSizeLiveshot()) 2393 ret = initFullLiveshot(); 2394 2395 /* Check if it's a raw snapshot or JPEG*/ 2396 if(mHalCamCtrl->isRawSnapshot()) { 2397 mSnapshotFormat = PICTURE_FORMAT_RAW; 2398 ret = initRawSnapshot(mNumOfSnapshot); 2399 }else{ 2400 //JPEG 2401 mSnapshotFormat = PICTURE_FORMAT_JPEG; 2402 if (mHdrInfo.hdr_on) { 2403 ret = initJPEGSnapshot(mHdrInfo.num_frame); 2404 } else { 2405 ret = initJPEGSnapshot(mNumOfSnapshot); 2406 } 2407 } 2408 if(ret != NO_ERROR) { 2409 ALOGE("%s : Error while Initializing snapshot",__func__); 2410 goto end; 2411 } 2412 2413 //Update Exiftag values. 2414 mHalCamCtrl->setExifTags(); 2415 2416 if (mSnapshotFormat == PICTURE_FORMAT_RAW) { 2417 ret = takePictureRaw(); 2418 goto end; 2419 } 2420 else{ 2421 ret = takePictureJPEG(); 2422 goto end; 2423 } 2424 2425 end: 2426 if (ret == NO_ERROR) { 2427 setSnapshotState(SNAPSHOT_STATE_IMAGE_CAPTURE_STRTD); 2428 mActive = true; 2429 } else { 2430 deInitBuffer(); 2431 } 2432 2433 ALOGV("%s: X", __func__); 2434 return ret; 2435 } 2436 2437 void QCameraStream_Snapshot::stopPolling(void) 2438 { 2439 mm_camera_ops_type_t ops_type; 2440 2441 if (mSnapshotFormat == PICTURE_FORMAT_JPEG) { 2442 ops_type = isZSLMode() ? MM_CAMERA_OPS_ZSL : MM_CAMERA_OPS_SNAPSHOT; 2443 }else 2444 ops_type = MM_CAMERA_OPS_RAW; 2445 2446 if( NO_ERROR != cam_ops_action(mCameraId, false, 2447 ops_type, this)) { 2448 ALOGE("%s: Failure stopping snapshot", __func__); 2449 } 2450 } 2451 2452 void QCameraStream_Snapshot::stop(void) 2453 { 2454 mm_camera_ops_type_t ops_type; 2455 status_t ret = NO_ERROR; 2456 2457 ALOGV("%s: E", __func__); 2458 2459 if(isLiveSnapshot() && mHalCamCtrl->mStateLiveshot) { 2460 if(getSnapshotState() == SNAPSHOT_STATE_JPEG_ENCODING) { 2461 ALOGV("Destroy Liveshot Jpeg Instance"); 2462 omxJpegAbort(); 2463 } 2464 mStopCallbackLock.lock(); 2465 deInitBuffer(); 2466 mHalCamCtrl->mStateLiveshot = false; 2467 mStopCallbackLock.unlock(); 2468 return; 2469 } 2470 2471 if(!mActive) { 2472 ALOGV("%s: Not Active return now", __func__); 2473 return; 2474 } 2475 mActive = false; 2476 mStopCallbackLock.lock(); 2477 if (getSnapshotState() != SNAPSHOT_STATE_UNINIT) { 2478 /* Stop polling for further frames */ 2479 stopPolling(); 2480 2481 if(getSnapshotState() == SNAPSHOT_STATE_JPEG_ENCODING) { 2482 mStopCallbackLock.unlock(); 2483 ALOGV("Destroy Jpeg Instance"); 2484 omxJpegAbort(); 2485 mStopCallbackLock.lock(); 2486 } 2487 /* Depending upon current state, we'll need to allocate-deallocate-deinit*/ 2488 deInitBuffer(); 2489 } 2490 2491 if(mSnapshotFormat == PICTURE_FORMAT_RAW) { 2492 ret= QCameraStream::deinitChannel(mCameraId, MM_CAMERA_CH_RAW); 2493 if(ret != MM_CAMERA_OK) { 2494 ALOGE("%s:Deinit RAW channel failed=%d\n", __func__, ret); 2495 } 2496 (void)cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_RAW, 2497 NULL, 2498 (mm_camera_register_buf_cb_type_t)NULL, 2499 NULL, 2500 NULL); 2501 } else { 2502 ret= QCameraStream::deinitChannel(mCameraId, MM_CAMERA_CH_SNAPSHOT); 2503 if(ret != MM_CAMERA_OK) { 2504 ALOGE("%s:Deinit Snapshot channel failed=%d\n", __func__, ret); 2505 } 2506 (void)cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_SNAPSHOT, 2507 NULL, 2508 (mm_camera_register_buf_cb_type_t)NULL, 2509 NULL, 2510 NULL); 2511 } 2512 2513 /* release is generally called in case of explicit call from 2514 upper-layer during disconnect. So we need to deinit everything 2515 whatever state we are in */ 2516 ALOGV("Calling omxjpegjoin from release\n"); 2517 omxJpegFinish(); 2518 #if 0 2519 omxJpegClose(); 2520 #endif 2521 mFullLiveshot = false; 2522 mStopCallbackLock.unlock(); 2523 ALOGV("%s: X", __func__); 2524 2525 } 2526 2527 void QCameraStream_Snapshot::release() 2528 { 2529 status_t ret = NO_ERROR; 2530 ALOGV("%s: E", __func__); 2531 //Mutex::Autolock l(&snapshotLock); 2532 2533 if(!mInit){ 2534 ALOGE("%s : Stream not Initalized",__func__); 2535 return; 2536 } 2537 2538 if(mActive) { 2539 this->stop(); 2540 mActive = false; 2541 } 2542 2543 /* release is generally called in case of explicit call from 2544 upper-layer during disconnect. So we need to deinit everything 2545 whatever state we are in */ 2546 2547 //deinit(); 2548 mInit = false; 2549 ALOGV("%s: X", __func__); 2550 2551 } 2552 2553 void QCameraStream_Snapshot::prepareHardware() 2554 { 2555 ALOGV("%s: E", __func__); 2556 2557 /* Prepare snapshot*/ 2558 cam_ops_action(mCameraId, 2559 true, 2560 MM_CAMERA_OPS_PREPARE_SNAPSHOT, 2561 this); 2562 ALOGV("%s: X", __func__); 2563 } 2564 2565 sp<IMemoryHeap> QCameraStream_Snapshot::getRawHeap() const 2566 { 2567 return ((mDisplayHeap != NULL) ? mDisplayHeap->mHeap : NULL); 2568 } 2569 2570 QCameraStream* 2571 QCameraStream_Snapshot::createInstance(int cameraId, 2572 camera_mode_t mode) 2573 { 2574 2575 QCameraStream* pme = new QCameraStream_Snapshot(cameraId, mode); 2576 2577 return pme; 2578 } 2579 2580 void QCameraStream_Snapshot::deleteInstance(QCameraStream *p) 2581 { 2582 if (p){ 2583 p->release(); 2584 delete p; 2585 p = NULL; 2586 } 2587 } 2588 2589 void QCameraStream_Snapshot::notifyWDenoiseEvent(cam_ctrl_status_t status, void * cookie) 2590 { 2591 camera_notify_callback notifyCb; 2592 camera_data_callback dataCb, jpgDataCb; 2593 int rc = NO_ERROR; 2594 mm_camera_ch_data_buf_t *frame = (mm_camera_ch_data_buf_t *)cookie; 2595 2596 ALOGV("%s: WDN Done status (%d) received",__func__,status); 2597 Mutex::Autolock lock(mStopCallbackLock); 2598 if (frame == NULL) { 2599 ALOGE("%s: cookie is returned NULL", __func__); 2600 } else { 2601 #if 0 2602 // first unmapping the fds 2603 mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, frame->snapshot.main.idx, mCameraId, 2604 CAM_SOCK_MSG_TYPE_FD_UNMAPPING); 2605 mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, frame->snapshot.thumbnail.idx, mCameraId, 2606 CAM_SOCK_MSG_TYPE_FD_UNMAPPING); 2607 #endif 2608 2609 // then do JPEG encoding 2610 rc = encodeDisplayAndSave(frame, 0); 2611 } 2612 2613 // send upperlayer callback for raw image (data or notify, not both) 2614 if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){ 2615 dataCb = mHalCamCtrl->mDataCb; 2616 } else { 2617 dataCb = NULL; 2618 } 2619 if((mHalCamCtrl->mNotifyCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)){ 2620 notifyCb = mHalCamCtrl->mNotifyCb; 2621 } else { 2622 notifyCb = NULL; 2623 } 2624 if(mHalCamCtrl->mDataCb && 2625 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) { 2626 /* get picture failed. Give jpeg callback with NULL data 2627 * to the application to restore to preview mode 2628 */ 2629 jpgDataCb = mHalCamCtrl->mDataCb; 2630 } else { 2631 jpgDataCb = NULL; 2632 } 2633 2634 // launch next WDN if there is more in WDN Queue 2635 lauchNextWDenoiseFromQueue(); 2636 2637 mStopCallbackLock.unlock(); 2638 2639 if (rc != NO_ERROR) 2640 { 2641 ALOGE("%s: Error while encoding/displaying/saving image", __func__); 2642 if (frame) { 2643 cam_evt_buf_done(mCameraId, frame); 2644 } 2645 2646 if (dataCb) { 2647 dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0], 2648 1, NULL, mHalCamCtrl->mCallbackCookie); 2649 } 2650 if (notifyCb) { 2651 notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie); 2652 } 2653 if (jpgDataCb) { 2654 jpgDataCb(CAMERA_MSG_COMPRESSED_IMAGE, 2655 NULL, 0, NULL, 2656 mHalCamCtrl->mCallbackCookie); 2657 } 2658 2659 if (frame != NULL) { 2660 free(frame); 2661 } 2662 } 2663 } 2664 2665 void QCameraStream_Snapshot::lauchNextWDenoiseFromQueue() 2666 { 2667 do { 2668 mm_camera_ch_data_buf_t *frame = NULL; 2669 if ( mWDNQueue.isEmpty() || 2670 (NULL == (frame = (mm_camera_ch_data_buf_t *)mWDNQueue.dequeue())) ) { 2671 // set the flag back to false when no WDN going on 2672 mIsDoingWDN = false; 2673 break; 2674 } 2675 2676 if ( NO_ERROR != doWaveletDenoise(frame) ) { 2677 ALOGE("%s: Error while doing wavelet denoise", __func__); 2678 if (frame != NULL) { 2679 free(frame); 2680 } 2681 } else { 2682 // we sent out req for WDN, so we can break here 2683 ALOGV("%s: Send out req for doing wavelet denoise, return here", __func__); 2684 break; 2685 } 2686 } while (true); 2687 } 2688 2689 status_t QCameraStream_Snapshot::doWaveletDenoise(mm_camera_ch_data_buf_t* frame) 2690 { 2691 status_t ret = NO_ERROR; 2692 cam_sock_packet_t packet; 2693 cam_ctrl_dimension_t dim; 2694 2695 ALOGV("%s: E", __func__); 2696 2697 #if 0 2698 // get dim on the fly 2699 memset(&dim, 0, sizeof(cam_ctrl_dimension_t)); 2700 ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim); 2701 if (NO_ERROR != ret) { 2702 ALOGE("%s: error - can't get dimension!", __func__); 2703 return FAILED_TRANSACTION; 2704 } 2705 2706 // send main frame mapping through domain socket 2707 if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, 2708 frame->snapshot.main.idx, 2709 frame->snapshot.main.frame->fd, 2710 dim.picture_frame_offset.frame_len, mCameraId, 2711 CAM_SOCK_MSG_TYPE_FD_MAPPING)) { 2712 ALOGE("%s: sending main frame mapping buf msg Failed", __func__); 2713 ret = FAILED_TRANSACTION; 2714 goto end; 2715 } 2716 2717 // send thumbnail frame mapping through domain socket 2718 if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, 2719 frame->snapshot.thumbnail.idx, 2720 frame->snapshot.thumbnail.frame->fd, 2721 dim.display_frame_offset.frame_len, mCameraId, 2722 CAM_SOCK_MSG_TYPE_FD_MAPPING)) { 2723 ALOGE("%s: sending thumbnail frame mapping buf msg Failed", __func__); 2724 ret = FAILED_TRANSACTION; 2725 goto end; 2726 } 2727 2728 #endif 2729 // ask deamon to start wdn operation 2730 if (NO_ERROR != sendWDenoiseStartMsg(frame)) { 2731 ALOGE("%s: sending thumbnail frame mapping buf msg Failed", __func__); 2732 ret = FAILED_TRANSACTION; 2733 goto end; 2734 } 2735 2736 end: 2737 ALOGV("%s: X", __func__); 2738 return ret; 2739 } 2740 2741 status_t QCameraStream_Snapshot::sendWDenoiseStartMsg(mm_camera_ch_data_buf_t * frame) 2742 { 2743 cam_sock_packet_t packet; 2744 memset(&packet, 0, sizeof(cam_sock_packet_t)); 2745 packet.msg_type = CAM_SOCK_MSG_TYPE_WDN_START; 2746 packet.payload.wdn_start.cookie = (unsigned long)frame; 2747 packet.payload.wdn_start.num_frames = MM_MAX_WDN_NUM; 2748 packet.payload.wdn_start.ext_mode[0] = MSM_V4L2_EXT_CAPTURE_MODE_MAIN; 2749 packet.payload.wdn_start.ext_mode[1] = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL; 2750 packet.payload.wdn_start.frame_idx[0] = frame->snapshot.main.idx; 2751 packet.payload.wdn_start.frame_idx[1] = frame->snapshot.thumbnail.idx; 2752 if ( cam_ops_sendmsg(mCameraId, &packet, sizeof(packet), 0) <= 0 ) { 2753 ALOGE("%s: sending start wavelet denoise msg failed", __func__); 2754 return FAILED_TRANSACTION; 2755 } 2756 return NO_ERROR; 2757 } 2758 2759 status_t QCameraStream_Snapshot::doHdrProcessing( ) 2760 { 2761 status_t rc = NO_ERROR; 2762 cam_sock_packet_t packet; 2763 int i; 2764 memset(&packet, 0, sizeof(cam_sock_packet_t)); 2765 packet.msg_type = CAM_SOCK_MSG_TYPE_HDR_START; 2766 packet.payload.hdr_pkg.cookie = (unsigned long)this; 2767 packet.payload.hdr_pkg.num_hdr_frames = mHdrInfo.num_frame; 2768 ALOGV("%s num frames = %d ", __func__, mHdrInfo.num_frame); 2769 for (i = 0; i < mHdrInfo.num_frame; i++) { 2770 packet.payload.hdr_pkg.hdr_main_idx[i] =mHdrInfo.recvd_frame[i]->snapshot.main.idx; 2771 packet.payload.hdr_pkg.hdr_thm_idx[i] = mHdrInfo.recvd_frame[i]->snapshot.thumbnail.idx; 2772 packet.payload.hdr_pkg.exp[i] = mHdrInfo.exp[i]; 2773 ALOGV("%s Adding buffer M %d T %d Exp %d into hdr pkg ", __func__, 2774 packet.payload.hdr_pkg.hdr_main_idx[i], 2775 packet.payload.hdr_pkg.hdr_thm_idx[i], 2776 packet.payload.hdr_pkg.exp[i]); 2777 } 2778 if (cam_ops_sendmsg(mCameraId, &packet, sizeof(packet), 0) <= 0) { 2779 ALOGE("%s: sending start HDR msg failed", __func__); 2780 rc= FAILED_TRANSACTION; 2781 } 2782 return rc; 2783 } 2784 2785 void QCameraStream_Snapshot::InitHdrInfoForSnapshot(bool Hdr_on, int number_frames, int *exp ) 2786 { 2787 mHdrInfo.hdr_on = Hdr_on; 2788 mHdrInfo.num_frame = number_frames; 2789 mHdrInfo.num_raw_received = 0; 2790 2791 if(number_frames) { 2792 memcpy(mHdrInfo.exp, exp, sizeof(int)*number_frames); 2793 } 2794 memset(&mHdrInfo.recvd_frame, 0, 2795 sizeof(mm_camera_ch_data_buf_t *)*MAX_HDR_EXP_FRAME_NUM); 2796 } 2797 2798 2799 void QCameraStream_Snapshot::notifyHdrEvent(cam_ctrl_status_t status, void * cookie) 2800 { 2801 camera_notify_callback notifyCb; 2802 camera_data_callback dataCb, jpgDataCb; 2803 int rc[3]; 2804 mm_camera_ch_data_buf_t *frame; 2805 int i; 2806 2807 ALOGV("%s: HDR Done status (%d) received",__func__,status); 2808 Mutex::Autolock lock(mStopCallbackLock); 2809 /* Regular frame */ 2810 frame = mHdrInfo.recvd_frame[0]; 2811 rc[0] = encodeDisplayAndSave(frame, 0); 2812 /* HDR frame */ 2813 frame = mHdrInfo.recvd_frame[2]; 2814 rc[2] = encodeDisplayAndSave(frame,0); 2815 2816 // send upperlayer callback for raw image (data or notify, not both) 2817 if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){ 2818 dataCb = mHalCamCtrl->mDataCb; 2819 } else { 2820 dataCb = NULL; 2821 } 2822 if((mHalCamCtrl->mNotifyCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)){ 2823 notifyCb = mHalCamCtrl->mNotifyCb; 2824 } else { 2825 notifyCb = NULL; 2826 } 2827 if(mHalCamCtrl->mDataCb && 2828 (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) { 2829 /* get picture failed. Give jpeg callback with NULL data 2830 * to the application to restore to preview mode 2831 */ 2832 jpgDataCb = mHalCamCtrl->mDataCb; 2833 } else { 2834 jpgDataCb = NULL; 2835 } 2836 2837 mStopCallbackLock.unlock(); 2838 2839 for (i =0; i<= 2; i++) { 2840 if(i==1) 2841 continue; 2842 if (rc[i] != NO_ERROR) 2843 { 2844 ALOGE("%s: Error while encoding/displaying/saving image", __func__); 2845 if (frame) { 2846 cam_evt_buf_done(mCameraId, mHdrInfo.recvd_frame[i]); 2847 } 2848 2849 if (dataCb) { 2850 dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0], 2851 1, NULL, mHalCamCtrl->mCallbackCookie); 2852 } 2853 if (notifyCb) { 2854 notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie); 2855 } 2856 if (jpgDataCb) { 2857 jpgDataCb(CAMERA_MSG_COMPRESSED_IMAGE, 2858 NULL, 0, NULL, 2859 mHalCamCtrl->mCallbackCookie); 2860 } 2861 2862 if ( mHdrInfo.recvd_frame[i] != NULL) { 2863 free( mHdrInfo.recvd_frame[i]); 2864 mHdrInfo.recvd_frame[i] = NULL; 2865 } 2866 } 2867 } 2868 2869 if (mHdrInfo.recvd_frame[1]) { 2870 cam_evt_buf_done(mCameraId, mHdrInfo.recvd_frame[1]); 2871 free( mHdrInfo.recvd_frame[1]); 2872 mHdrInfo.recvd_frame[1] = NULL; 2873 } 2874 } 2875 2876 }; // namespace android 2877 2878