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