QCamera2HWICallbacks.cpp revision fbe69a7ac63f99c63d50d9abaed766c81d2aab13
1/* Copyright (c) 2012-2013, The Linux Foundataion. All rights reserved. 2* 3* Redistribution and use in source and binary forms, with or without 4* modification, are permitted provided that the following conditions are 5* met: 6* * Redistributions of source code must retain the above copyright 7* notice, this list of conditions and the following disclaimer. 8* * Redistributions in binary form must reproduce the above 9* copyright notice, this list of conditions and the following 10* disclaimer in the documentation and/or other materials provided 11* with the distribution. 12* * Neither the name of The Linux Foundation nor the names of its 13* contributors may be used to endorse or promote products derived 14* from this software without specific prior written permission. 15* 16* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27* 28*/ 29 30#define LOG_TAG "QCamera2HWI" 31 32#include <fcntl.h> 33#include <utils/Errors.h> 34#include <utils/Timers.h> 35#include "QCamera2HWI.h" 36 37namespace qcamera { 38 39/*=========================================================================== 40 * FUNCTION : zsl_channel_cb 41 * 42 * DESCRIPTION: helper function to handle ZSL superbuf callback directly from 43 * mm-camera-interface 44 * 45 * PARAMETERS : 46 * @recvd_frame : received super buffer 47 * @userdata : user data ptr 48 * 49 * RETURN : None 50 * 51 * NOTE : recvd_frame will be released after this call by caller, so if 52 * async operation needed for recvd_frame, it's our responsibility 53 * to save a copy for this variable to be used later. 54 *==========================================================================*/ 55void QCamera2HardwareInterface::zsl_channel_cb(mm_camera_super_buf_t *recvd_frame, 56 void *userdata) 57{ 58 ALOGD("[KPI Perf] %s: E",__func__); 59 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 60 if (pme == NULL || 61 pme->mCameraHandle == NULL || 62 pme->mCameraHandle->camera_handle != recvd_frame->camera_handle){ 63 ALOGE("%s: camera obj not valid", __func__); 64 return; 65 } 66 67 QCameraChannel *pChannel = pme->m_channels[QCAMERA_CH_TYPE_ZSL]; 68 if (pChannel == NULL || 69 pChannel->getMyHandle() != recvd_frame->ch_id) { 70 ALOGE("%s: ZSL channel doesn't exist, return here", __func__); 71 return; 72 } 73 74 // save a copy for the superbuf 75 mm_camera_super_buf_t* frame = 76 (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t)); 77 if (frame == NULL) { 78 ALOGE("%s: Error allocating memory to save received_frame structure.", __func__); 79 pChannel->bufDone(recvd_frame); 80 return; 81 } 82 *frame = *recvd_frame; 83 84 // send to postprocessor 85 pme->m_postprocessor.processData(frame); 86 87 ALOGD("[KPI Perf] %s: X", __func__); 88} 89 90/*=========================================================================== 91 * FUNCTION : capture_channel_cb_routine 92 * 93 * DESCRIPTION: helper function to handle snapshot superbuf callback directly from 94 * mm-camera-interface 95 * 96 * PARAMETERS : 97 * @recvd_frame : received super buffer 98 * @userdata : user data ptr 99 * 100 * RETURN : None 101 * 102 * NOTE : recvd_frame will be released after this call by caller, so if 103 * async operation needed for recvd_frame, it's our responsibility 104 * to save a copy for this variable to be used later. 105*==========================================================================*/ 106void QCamera2HardwareInterface::capture_channel_cb_routine(mm_camera_super_buf_t *recvd_frame, 107 void *userdata) 108{ 109 ALOGD("[KPI Perf] %s: E", __func__); 110 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 111 if (pme == NULL || 112 pme->mCameraHandle == NULL || 113 pme->mCameraHandle->camera_handle != recvd_frame->camera_handle){ 114 ALOGE("%s: camera obj not valid", __func__); 115 // simply free super frame 116 free(recvd_frame); 117 return; 118 } 119 120 QCameraChannel *pChannel = pme->m_channels[QCAMERA_CH_TYPE_CAPTURE]; 121 if (pChannel == NULL || 122 pChannel->getMyHandle() != recvd_frame->ch_id) { 123 ALOGE("%s: Capture channel doesn't exist, return here", __func__); 124 return; 125 } 126 127 // save a copy for the superbuf 128 mm_camera_super_buf_t* frame = 129 (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t)); 130 if (frame == NULL) { 131 ALOGE("%s: Error allocating memory to save received_frame structure.", __func__); 132 pChannel->bufDone(recvd_frame); 133 return; 134 } 135 *frame = *recvd_frame; 136 137 // send to postprocessor 138 pme->m_postprocessor.processData(frame); 139 140/* START of test register face image for face authentication */ 141#ifdef QCOM_TEST_FACE_REGISTER_FACE 142 static uint8_t bRunFaceReg = 1; 143 144 if (bRunFaceReg > 0) { 145 // find snapshot frame 146 QCameraStream *main_stream = NULL; 147 mm_camera_buf_def_t *main_frame = NULL; 148 for (int i = 0; i < recvd_frame->num_bufs; i++) { 149 QCameraStream *pStream = 150 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id); 151 if (pStream != NULL) { 152 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { 153 main_stream = pStream; 154 main_frame = recvd_frame->bufs[i]; 155 break; 156 } 157 } 158 } 159 if (main_stream != NULL && main_frame != NULL) { 160 int32_t faceId = -1; 161 cam_pp_offline_src_config_t config; 162 memset(&config, 0, sizeof(cam_pp_offline_src_config_t)); 163 config.num_of_bufs = 1; 164 main_stream->getFormat(config.input_fmt); 165 main_stream->getFrameDimension(config.input_dim); 166 main_stream->getFrameOffset(config.input_buf_planes.plane_info); 167 ALOGD("DEBUG: registerFaceImage E"); 168 int32_t rc = pme->registerFaceImage(main_frame->buffer, &config, faceId); 169 ALOGD("DEBUG: registerFaceImage X, ret=%d, faceId=%d", rc, faceId); 170 bRunFaceReg = 0; 171 } 172 } 173 174#endif 175/* END of test register face image for face authentication */ 176 177 ALOGD("[KPI Perf] %s: X", __func__); 178} 179 180/*=========================================================================== 181 * FUNCTION : postproc_channel_cb_routine 182 * 183 * DESCRIPTION: helper function to handle postprocess superbuf callback directly from 184 * mm-camera-interface 185 * 186 * PARAMETERS : 187 * @recvd_frame : received super buffer 188 * @userdata : user data ptr 189 * 190 * RETURN : None 191 * 192 * NOTE : recvd_frame will be released after this call by caller, so if 193 * async operation needed for recvd_frame, it's our responsibility 194 * to save a copy for this variable to be used later. 195*==========================================================================*/ 196void QCamera2HardwareInterface::postproc_channel_cb_routine(mm_camera_super_buf_t *recvd_frame, 197 void *userdata) 198{ 199 ALOGD("[KPI Perf] %s: E", __func__); 200 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 201 if (pme == NULL || 202 pme->mCameraHandle == NULL || 203 pme->mCameraHandle->camera_handle != recvd_frame->camera_handle){ 204 ALOGE("%s: camera obj not valid", __func__); 205 // simply free super frame 206 free(recvd_frame); 207 return; 208 } 209 210 // save a copy for the superbuf 211 mm_camera_super_buf_t* frame = 212 (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t)); 213 if (frame == NULL) { 214 ALOGE("%s: Error allocating memory to save received_frame structure.", __func__); 215 return; 216 } 217 *frame = *recvd_frame; 218 219 // send to postprocessor 220 pme->m_postprocessor.processPPData(frame); 221 222 ALOGD("[KPI Perf] %s: X", __func__); 223} 224 225/*=========================================================================== 226 * FUNCTION : preview_stream_cb_routine 227 * 228 * DESCRIPTION: helper function to handle preview frame from preview stream in 229 * normal case with display. 230 * 231 * PARAMETERS : 232 * @super_frame : received super buffer 233 * @stream : stream object 234 * @userdata : user data ptr 235 * 236 * RETURN : None 237 * 238 * NOTE : caller passes the ownership of super_frame, it's our 239 * responsibility to free super_frame once it's done. The new 240 * preview frame will be sent to display, and an older frame 241 * will be dequeued from display and needs to be returned back 242 * to kernel for future use. 243 *==========================================================================*/ 244void QCamera2HardwareInterface::preview_stream_cb_routine(mm_camera_super_buf_t *super_frame, 245 QCameraStream * stream, 246 void *userdata) 247{ 248 ALOGD("[KPI Perf] %s : BEGIN", __func__); 249 int err = NO_ERROR; 250 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 251 QCameraGrallocMemory *memory = (QCameraGrallocMemory *)super_frame->bufs[0]->mem_info; 252 253 if (pme == NULL) { 254 ALOGE("%s: Invalid hardware object", __func__); 255 free(super_frame); 256 return; 257 } 258 if (memory == NULL) { 259 ALOGE("%s: Invalid memory object", __func__); 260 free(super_frame); 261 return; 262 } 263 264 mm_camera_buf_def_t *frame = super_frame->bufs[0]; 265 if (NULL == frame) { 266 ALOGE("%s: preview frame is NLUL", __func__); 267 free(super_frame); 268 return; 269 } 270 271 if (!pme->needProcessPreviewFrame()) { 272 ALOGE("%s: preview is not running, no need to process", __func__); 273 stream->bufDone(frame->buf_idx); 274 free(super_frame); 275 return; 276 } 277 278 if (pme->needDebugFps()) { 279 pme->debugShowPreviewFPS(); 280 } 281 282 int idx = frame->buf_idx; 283 pme->dumpFrameToFile(frame->buffer, frame->frame_len, 284 frame->frame_idx, QCAMERA_DUMP_FRM_PREVIEW); 285 286 // Display the buffer. 287 int dequeuedIdx = memory->displayBuffer(idx); 288 if (dequeuedIdx < 0 || dequeuedIdx >= memory->getCnt()) { 289 ALOGD("%s: Invalid dequeued buffer index %d from display", 290 __func__, dequeuedIdx); 291 } else { 292 // Return dequeued buffer back to driver 293 err = stream->bufDone(dequeuedIdx); 294 if ( err < 0) { 295 ALOGE("stream bufDone failed %d", err); 296 } 297 } 298 299 // Handle preview data callback 300 if (pme->mDataCb != NULL && pme->msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_FRAME) > 0) { 301 camera_memory_t *previewMem = NULL; 302 camera_memory_t *data = NULL; 303 int previewBufSize; 304 cam_dimension_t preview_dim; 305 cam_format_t previewFmt; 306 stream->getFrameDimension(preview_dim); 307 stream->getFormat(previewFmt); 308 309 /* The preview buffer size in the callback should be (width*height*bytes_per_pixel) 310 * As all preview formats we support, use 12 bits per pixel, buffer size = previewWidth * previewHeight * 3/2. 311 * We need to put a check if some other formats are supported in future. */ 312 if ((previewFmt == CAM_FORMAT_YUV_420_NV21) || 313 (previewFmt == CAM_FORMAT_YUV_420_NV12) || 314 (previewFmt == CAM_FORMAT_YUV_420_YV12)) { 315 if(previewFmt == CAM_FORMAT_YUV_420_YV12) { 316 previewBufSize = ((preview_dim.width+15)/16) * 16 * preview_dim.height + 317 ((preview_dim.width/2+15)/16) * 16* preview_dim.height; 318 } else { 319 previewBufSize = preview_dim.width * preview_dim.height * 3/2; 320 } 321 if(previewBufSize != memory->getSize(idx)) { 322 previewMem = pme->mGetMemory(memory->getFd(idx), 323 previewBufSize, 1, pme->mCallbackCookie); 324 if (!previewMem || !previewMem->data) { 325 ALOGE("%s: mGetMemory failed.\n", __func__); 326 } else { 327 data = previewMem; 328 } 329 } else 330 data = memory->getMemory(idx, false); 331 } else { 332 data = memory->getMemory(idx, false); 333 ALOGE("%s: Invalid preview format, buffer size in preview callback may be wrong.", __func__); 334 } 335 qcamera_callback_argm_t cbArg; 336 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 337 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 338 cbArg.msg_type = CAMERA_MSG_PREVIEW_FRAME; 339 cbArg.data = data; 340 if ( previewMem ) { 341 cbArg.user_data = previewMem; 342 cbArg.release_cb = releaseCameraMemory; 343 } 344 cbArg.cookie = pme; 345 pme->m_cbNotifier.notifyCallback(cbArg); 346 } 347 348 free(super_frame); 349 ALOGD("[KPI Perf] %s : END", __func__); 350 return; 351} 352 353/*=========================================================================== 354 * FUNCTION : nodisplay_preview_stream_cb_routine 355 * 356 * DESCRIPTION: helper function to handle preview frame from preview stream in 357 * no-display case 358 * 359 * PARAMETERS : 360 * @super_frame : received super buffer 361 * @stream : stream object 362 * @userdata : user data ptr 363 * 364 * RETURN : None 365 * 366 * NOTE : caller passes the ownership of super_frame, it's our 367 * responsibility to free super_frame once it's done. 368 *==========================================================================*/ 369void QCamera2HardwareInterface::nodisplay_preview_stream_cb_routine( 370 mm_camera_super_buf_t *super_frame, 371 QCameraStream *stream, 372 void * userdata) 373{ 374 ALOGD("[KPI Perf] %s E",__func__); 375 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 376 if (pme == NULL || 377 pme->mCameraHandle == NULL || 378 pme->mCameraHandle->camera_handle != super_frame->camera_handle){ 379 ALOGE("%s: camera obj not valid", __func__); 380 // simply free super frame 381 free(super_frame); 382 return; 383 } 384 mm_camera_buf_def_t *frame = super_frame->bufs[0]; 385 if (NULL == frame) { 386 ALOGE("%s: preview frame is NLUL", __func__); 387 free(super_frame); 388 return; 389 } 390 391 if (!pme->needProcessPreviewFrame()) { 392 ALOGD("%s: preview is not running, no need to process", __func__); 393 stream->bufDone(frame->buf_idx); 394 free(super_frame); 395 return; 396 } 397 398 if (pme->needDebugFps()) { 399 pme->debugShowPreviewFPS(); 400 } 401 402 QCameraMemory *previewMemObj = (QCameraMemory *)frame->mem_info; 403 camera_memory_t *preview_mem = NULL; 404 if (previewMemObj != NULL) { 405 preview_mem = previewMemObj->getMemory(frame->buf_idx, false); 406 } 407 if (NULL != previewMemObj && NULL != preview_mem) { 408 pme->dumpFrameToFile(frame->buffer, frame->frame_len, 409 frame->frame_idx, QCAMERA_DUMP_FRM_PREVIEW); 410 411 if (pme->needProcessPreviewFrame() && 412 pme->mDataCb != NULL && 413 pme->msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_FRAME) > 0 ) { 414 qcamera_callback_argm_t cbArg; 415 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 416 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 417 cbArg.msg_type = CAMERA_MSG_PREVIEW_FRAME; 418 cbArg.data = preview_mem; 419 int user_data = frame->buf_idx; 420 cbArg.user_data = ( void * ) user_data; 421 cbArg.cookie = stream; 422 cbArg.release_cb = returnStreamBuffer; 423 pme->m_cbNotifier.notifyCallback(cbArg); 424 } else { 425 stream->bufDone(frame->buf_idx); 426 } 427 } 428 free(super_frame); 429 ALOGD("[KPI Perf] %s X",__func__); 430} 431 432/*=========================================================================== 433 * FUNCTION : postview_stream_cb_routine 434 * 435 * DESCRIPTION: helper function to handle post frame from postview stream 436 * 437 * PARAMETERS : 438 * @super_frame : received super buffer 439 * @stream : stream object 440 * @userdata : user data ptr 441 * 442 * RETURN : None 443 * 444 * NOTE : caller passes the ownership of super_frame, it's our 445 * responsibility to free super_frame once it's done. 446 *==========================================================================*/ 447void QCamera2HardwareInterface::postview_stream_cb_routine(mm_camera_super_buf_t *super_frame, 448 QCameraStream *stream, 449 void *userdata) 450{ 451 int err = NO_ERROR; 452 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 453 QCameraGrallocMemory *memory = (QCameraGrallocMemory *)super_frame->bufs[0]->mem_info; 454 455 if (pme == NULL) { 456 ALOGE("%s: Invalid hardware object", __func__); 457 free(super_frame); 458 return; 459 } 460 if (memory == NULL) { 461 ALOGE("%s: Invalid memory object", __func__); 462 free(super_frame); 463 return; 464 } 465 466 ALOGD("[KPI Perf] %s : BEGIN", __func__); 467 468 mm_camera_buf_def_t *frame = super_frame->bufs[0]; 469 if (NULL == frame) { 470 ALOGE("%s: preview frame is NLUL", __func__); 471 free(super_frame); 472 return; 473 } 474 475 QCameraMemory *memObj = (QCameraMemory *)frame->mem_info; 476 if (NULL != memObj) { 477 pme->dumpFrameToFile(frame->buffer, frame->frame_len, 478 frame->frame_idx, QCAMERA_DUMP_FRM_THUMBNAIL); 479 } 480 481 // Display the buffer. 482 int dequeuedIdx = memory->displayBuffer(frame->buf_idx); 483 if (dequeuedIdx < 0 || dequeuedIdx >= memory->getCnt()) { 484 ALOGD("%s: Invalid dequeued buffer index %d", 485 __func__, dequeuedIdx); 486 free(super_frame); 487 return; 488 } 489 490 // Return dequeued buffer back to driver 491 err = stream->bufDone(dequeuedIdx); 492 if ( err < 0) { 493 ALOGE("stream bufDone failed %d", err); 494 } 495 496 free(super_frame); 497 ALOGD("[KPI Perf] %s : END", __func__); 498 return; 499} 500 501/*=========================================================================== 502 * FUNCTION : video_stream_cb_routine 503 * 504 * DESCRIPTION: helper function to handle video frame from video stream 505 * 506 * PARAMETERS : 507 * @super_frame : received super buffer 508 * @stream : stream object 509 * @userdata : user data ptr 510 * 511 * RETURN : None 512 * 513 * NOTE : caller passes the ownership of super_frame, it's our 514 * responsibility to free super_frame once it's done. video 515 * frame will be sent to video encoder. Once video encoder is 516 * done with the video frame, it will call another API 517 * (release_recording_frame) to return the frame back 518 *==========================================================================*/ 519void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *super_frame, 520 QCameraStream */*stream*/, 521 void *userdata) 522{ 523 ALOGD("[KPI Perf] %s : BEGIN", __func__); 524 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 525 if (pme == NULL || 526 pme->mCameraHandle == NULL || 527 pme->mCameraHandle->camera_handle != super_frame->camera_handle){ 528 ALOGE("%s: camera obj not valid", __func__); 529 // simply free super frame 530 free(super_frame); 531 return; 532 } 533 mm_camera_buf_def_t *frame = super_frame->bufs[0]; 534 535 if (pme->needDebugFps()) { 536 pme->debugShowVideoFPS(); 537 } 538 539 ALOGE("%s: Stream(%d), Timestamp: %ld %ld", 540 __func__, 541 frame->stream_id, 542 frame->ts.tv_sec, 543 frame->ts.tv_nsec); 544 545 nsecs_t timeStamp = nsecs_t(frame->ts.tv_sec) * 1000000000LL + frame->ts.tv_nsec; 546 ALOGE("Send Video frame to services/encoder TimeStamp : %lld", timeStamp); 547 QCameraMemory *videoMemObj = (QCameraMemory *)frame->mem_info; 548 camera_memory_t *video_mem = NULL; 549 if (NULL != videoMemObj) { 550 video_mem = videoMemObj->getMemory(frame->buf_idx, (pme->mStoreMetaDataInFrame > 0)? true : false); 551 } 552 if (NULL != videoMemObj && NULL != video_mem) { 553 pme->dumpFrameToFile(frame->buffer, frame->frame_len, 554 frame->frame_idx, QCAMERA_DUMP_FRM_VIDEO); 555 if ((pme->mDataCbTimestamp != NULL) && 556 pme->msgTypeEnabledWithLock(CAMERA_MSG_VIDEO_FRAME) > 0) { 557 qcamera_callback_argm_t cbArg; 558 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 559 cbArg.cb_type = QCAMERA_DATA_TIMESTAMP_CALLBACK; 560 cbArg.msg_type = CAMERA_MSG_VIDEO_FRAME; 561 cbArg.data = video_mem; 562 cbArg.timestamp = timeStamp; 563 pme->m_cbNotifier.notifyCallback(cbArg); 564 } 565 } 566 free(super_frame); 567 ALOGD("[KPI Perf] %s : END", __func__); 568} 569 570/*=========================================================================== 571 * FUNCTION : snapshot_stream_cb_routine 572 * 573 * DESCRIPTION: helper function to handle snapshot frame from snapshot stream 574 * 575 * PARAMETERS : 576 * @super_frame : received super buffer 577 * @stream : stream object 578 * @userdata : user data ptr 579 * 580 * RETURN : None 581 * 582 * NOTE : caller passes the ownership of super_frame, it's our 583 * responsibility to free super_frame once it's done. For 584 * snapshot, it need to send to postprocessor for jpeg 585 * encoding, therefore the ownership of super_frame will be 586 * hand to postprocessor. 587 *==========================================================================*/ 588void QCamera2HardwareInterface::snapshot_stream_cb_routine(mm_camera_super_buf_t *super_frame, 589 QCameraStream * /*stream*/, 590 void *userdata) 591{ 592 ALOGD("[KPI Perf] %s: E", __func__); 593 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 594 if (pme == NULL || 595 pme->mCameraHandle == NULL || 596 pme->mCameraHandle->camera_handle != super_frame->camera_handle){ 597 ALOGE("%s: camera obj not valid", __func__); 598 // simply free super frame 599 free(super_frame); 600 return; 601 } 602 603 pme->m_postprocessor.processData(super_frame); 604 605 ALOGD("[KPI Perf] %s: X", __func__); 606} 607 608/*=========================================================================== 609 * FUNCTION : raw_stream_cb_routine 610 * 611 * DESCRIPTION: helper function to handle raw dump frame from raw stream 612 * 613 * PARAMETERS : 614 * @super_frame : received super buffer 615 * @stream : stream object 616 * @userdata : user data ptr 617 * 618 * RETURN : None 619 * 620 * NOTE : caller passes the ownership of super_frame, it's our 621 * responsibility to free super_frame once it's done. For raw 622 * frame, there is no need to send to postprocessor for jpeg 623 * encoding. this function will play shutter and send the data 624 * callback to upper layer. Raw frame buffer will be returned 625 * back to kernel, and frame will be free after use. 626 *==========================================================================*/ 627void QCamera2HardwareInterface::raw_stream_cb_routine(mm_camera_super_buf_t * super_frame, 628 QCameraStream * /*stream*/, 629 void * userdata) 630{ 631 ALOGD("[KPI Perf] %s : BEGIN", __func__); 632 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 633 if (pme == NULL || 634 pme->mCameraHandle == NULL || 635 pme->mCameraHandle->camera_handle != super_frame->camera_handle){ 636 ALOGE("%s: camera obj not valid", __func__); 637 // simply free super frame 638 free(super_frame); 639 return; 640 } 641 642 pme->m_postprocessor.processRawData(super_frame); 643 ALOGD("[KPI Perf] %s : END", __func__); 644} 645 646/*=========================================================================== 647 * FUNCTION : metadata_stream_cb_routine 648 * 649 * DESCRIPTION: helper function to handle metadata frame from metadata stream 650 * 651 * PARAMETERS : 652 * @super_frame : received super buffer 653 * @stream : stream object 654 * @userdata : user data ptr 655 * 656 * RETURN : None 657 * 658 * NOTE : caller passes the ownership of super_frame, it's our 659 * responsibility to free super_frame once it's done. Metadata 660 * could have valid entries for face detection result or 661 * histogram statistics information. 662 *==========================================================================*/ 663void QCamera2HardwareInterface::metadata_stream_cb_routine(mm_camera_super_buf_t * super_frame, 664 QCameraStream * stream, 665 void * userdata) 666{ 667 ALOGV("[KPI Perf] %s : BEGIN", __func__); 668 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 669 if (pme == NULL || 670 pme->mCameraHandle == NULL || 671 pme->mCameraHandle->camera_handle != super_frame->camera_handle){ 672 ALOGE("%s: camera obj not valid", __func__); 673 // simply free super frame 674 free(super_frame); 675 return; 676 } 677 678 mm_camera_buf_def_t *frame = super_frame->bufs[0]; 679 cam_metadata_info_t *pMetaData = (cam_metadata_info_t *)frame->buffer; 680 681 if (pMetaData->is_faces_valid) { 682 if (pMetaData->faces_data.num_faces_detected > MAX_ROI) { 683 ALOGE("%s: Invalid number of faces %d", 684 __func__, pMetaData->faces_data.num_faces_detected); 685 } else { 686 // process face detection result 687 pme->processFaceDetectionResult(&pMetaData->faces_data); 688 } 689 } 690 691 if (pMetaData->is_stats_valid) { 692 // process histogram statistics info 693 pme->processHistogramStats(pMetaData->stats_data); 694 } 695 696 if (pMetaData->is_focus_valid) { 697 // process focus info 698 qcamera_sm_internal_evt_payload_t *payload = 699 (qcamera_sm_internal_evt_payload_t *)malloc(sizeof(qcamera_sm_internal_evt_payload_t)); 700 if (NULL != payload) { 701 memset(payload, 0, sizeof(qcamera_sm_internal_evt_payload_t)); 702 payload->evt_type = QCAMERA_INTERNAL_EVT_FOCUS_UPDATE; 703 payload->focus_data = pMetaData->focus_data; 704 int32_t rc = pme->processEvt(QCAMERA_SM_EVT_EVT_INTERNAL, payload); 705 if (rc != NO_ERROR) { 706 ALOGE("%s: processEVt failed", __func__); 707 free(payload); 708 payload = NULL; 709 710 } 711 } else { 712 ALOGE("%s: No memory for qcamera_sm_internal_evt_payload_t", __func__); 713 } 714 } 715 716 if (pMetaData->is_crop_valid) { 717 if (pMetaData->crop_data.num_of_streams > MAX_NUM_STREAMS) { 718 ALOGE("%s: Invalid num_of_streams %d in crop_data", __func__, 719 pMetaData->crop_data.num_of_streams); 720 } else { 721 pme->processZoomEvent(pMetaData->crop_data); 722 } 723 } 724 725 if (pMetaData->is_prep_snapshot_done_valid) { 726 qcamera_sm_internal_evt_payload_t *payload = 727 (qcamera_sm_internal_evt_payload_t *)malloc(sizeof(qcamera_sm_internal_evt_payload_t)); 728 if (NULL != payload) { 729 memset(payload, 0, sizeof(qcamera_sm_internal_evt_payload_t)); 730 payload->evt_type = QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE; 731 payload->prep_snapshot_state = pMetaData->prep_snapshot_done_state; 732 int32_t rc = pme->processEvt(QCAMERA_SM_EVT_EVT_INTERNAL, payload); 733 if (rc != NO_ERROR) { 734 ALOGE("%s: processEVt failed", __func__); 735 free(payload); 736 payload = NULL; 737 738 } 739 } else { 740 ALOGE("%s: No memory for qcamera_sm_internal_evt_payload_t", __func__); 741 } 742 } 743 744 stream->bufDone(frame->buf_idx); 745 free(super_frame); 746 747 ALOGV("[KPI Perf] %s : END", __func__); 748} 749 750/*=========================================================================== 751 * FUNCTION : reprocess_stream_cb_routine 752 * 753 * DESCRIPTION: helper function to handle reprocess frame from reprocess stream 754 (after reprocess, e.g., ZSL snapshot frame after WNR if 755 * WNR is enabled) 756 * 757 * PARAMETERS : 758 * @super_frame : received super buffer 759 * @stream : stream object 760 * @userdata : user data ptr 761 * 762 * RETURN : None 763 * 764 * NOTE : caller passes the ownership of super_frame, it's our 765 * responsibility to free super_frame once it's done. In this 766 * case, reprocessed frame need to be passed to postprocessor 767 * for jpeg encoding. 768 *==========================================================================*/ 769void QCamera2HardwareInterface::reprocess_stream_cb_routine(mm_camera_super_buf_t * super_frame, 770 QCameraStream * /*stream*/, 771 void * userdata) 772{ 773 ALOGD("[KPI Perf] %s: E", __func__); 774 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 775 if (pme == NULL || 776 pme->mCameraHandle == NULL || 777 pme->mCameraHandle->camera_handle != super_frame->camera_handle){ 778 ALOGE("%s: camera obj not valid", __func__); 779 // simply free super frame 780 free(super_frame); 781 return; 782 } 783 784 pme->m_postprocessor.processPPData(super_frame); 785 786 ALOGD("[KPI Perf] %s: X", __func__); 787} 788 789/*=========================================================================== 790 * FUNCTION : dumpFrameToFile 791 * 792 * DESCRIPTION: helper function to dump frame into file for debug purpose. 793 * 794 * PARAMETERS : 795 * @data : data ptr 796 * @size : length of data buffer 797 * @index : identifier for data 798 * @dump_type : type of the frame to be dumped. Only such 799 * dump type is enabled, the frame will be 800 * dumped into a file. 801 * 802 * RETURN : None 803 *==========================================================================*/ 804void QCamera2HardwareInterface::dumpFrameToFile(const void *data, 805 uint32_t size, 806 int index, 807 int dump_type) 808{ 809 char value[PROPERTY_VALUE_MAX]; 810 property_get("persist.camera.dumpimg", value, "0"); 811 int32_t enabled = atoi(value); 812 int frm_num = 0; 813 uint32_t skip_mode = 0; 814 815 char buf[32]; 816 cam_dimension_t dim; 817 memset(buf, 0, sizeof(buf)); 818 memset(&dim, 0, sizeof(dim)); 819 820 if(enabled & QCAMERA_DUMP_FRM_MASK_ALL) { 821 if((enabled & dump_type) && data) { 822 frm_num = ((enabled & 0xffff0000) >> 16); 823 if(frm_num == 0) { 824 frm_num = 10; //default 10 frames 825 } 826 if(frm_num > 256) { 827 frm_num = 256; //256 buffers cycle around 828 } 829 skip_mode = ((enabled & 0x0000ff00) >> 8); 830 if(skip_mode == 0) { 831 skip_mode = 1; //no-skip 832 } 833 834 if( mDumpSkipCnt % skip_mode == 0) { 835 if((frm_num == 256) && (mDumpFrmCnt >= frm_num)) { 836 // reset frame count if cycling 837 mDumpFrmCnt = 0; 838 } 839 if (mDumpFrmCnt >= 0 && mDumpFrmCnt <= frm_num) { 840 switch (dump_type) { 841 case QCAMERA_DUMP_FRM_PREVIEW: 842 { 843 mParameters.getStreamDimension(CAM_STREAM_TYPE_PREVIEW, dim); 844 snprintf(buf, sizeof(buf), "/data/%dp_%dx%d_%d.yuv", 845 mDumpFrmCnt, dim.width, dim.height, index); 846 } 847 break; 848 case QCAMERA_DUMP_FRM_THUMBNAIL: 849 { 850 mParameters.getStreamDimension(CAM_STREAM_TYPE_POSTVIEW, dim); 851 snprintf(buf, sizeof(buf), "/data/%dt_%dx%d_%d.yuv", 852 mDumpFrmCnt, dim.width, dim.height, index); 853 } 854 break; 855 case QCAMERA_DUMP_FRM_SNAPSHOT: 856 { 857 mParameters.getStreamDimension(CAM_STREAM_TYPE_SNAPSHOT, dim); 858 snprintf(buf, sizeof(buf), "/data/%ds_%dx%d_%d.yuv", 859 mDumpFrmCnt, dim.width, dim.height, index); 860 } 861 break; 862 case QCAMERA_DUMP_FRM_VIDEO: 863 { 864 mParameters.getStreamDimension(CAM_STREAM_TYPE_VIDEO, dim); 865 snprintf(buf, sizeof(buf), "/data/%dv_%dx%d_%d.yuv", 866 mDumpFrmCnt, dim.width, dim.height, index); 867 } 868 break; 869 case QCAMERA_DUMP_FRM_RAW: 870 { 871 mParameters.getStreamDimension(CAM_STREAM_TYPE_RAW, dim); 872 snprintf(buf, sizeof(buf), "/data/%dr_%dx%d_%d.yuv", 873 mDumpFrmCnt, dim.width, dim.height, index); 874 } 875 break; 876 case QCAMERA_DUMP_FRM_JPEG: 877 { 878 mParameters.getStreamDimension(CAM_STREAM_TYPE_SNAPSHOT, dim); 879 snprintf(buf, sizeof(buf), "/data/%dj_%dx%d_%d.yuv", 880 mDumpFrmCnt, dim.width, dim.height, index); 881 } 882 break; 883 default: 884 ALOGE("%s: Not supported for dumping stream type %d", 885 __func__, dump_type); 886 return; 887 } 888 889 ALOGD("dump %s size =%d, data = %p", buf, size, data); 890 int file_fd = open(buf, O_RDWR | O_CREAT, 0777); 891 if (file_fd > 0) { 892 int written_len = write(file_fd, data, size); 893 ALOGD("%s: written number of bytes %d\n", __func__, written_len); 894 close(file_fd); 895 } else { 896 ALOGE("%s: fail t open file for image dumping", __func__); 897 } 898 mDumpFrmCnt++; 899 } 900 } 901 mDumpSkipCnt++; 902 } 903 } else { 904 mDumpFrmCnt = 0; 905 } 906} 907 908/*=========================================================================== 909 * FUNCTION : debugShowVideoFPS 910 * 911 * DESCRIPTION: helper function to log video frame FPS for debug purpose. 912 * 913 * PARAMETERS : None 914 * 915 * RETURN : None 916 *==========================================================================*/ 917void QCamera2HardwareInterface::debugShowVideoFPS() 918{ 919 static int n_vFrameCount = 0; 920 static int n_vLastFrameCount = 0; 921 static nsecs_t n_vLastFpsTime = 0; 922 static float n_vFps = 0; 923 n_vFrameCount++; 924 nsecs_t now = systemTime(); 925 nsecs_t diff = now - n_vLastFpsTime; 926 if (diff > ms2ns(250)) { 927 n_vFps = ((n_vFrameCount - n_vLastFrameCount) * float(s2ns(1))) / diff; 928 ALOGE("Video Frames Per Second: %.4f", n_vFps); 929 n_vLastFpsTime = now; 930 n_vLastFrameCount = n_vFrameCount; 931 } 932} 933 934/*=========================================================================== 935 * FUNCTION : debugShowPreviewFPS 936 * 937 * DESCRIPTION: helper function to log preview frame FPS for debug purpose. 938 * 939 * PARAMETERS : None 940 * 941 * RETURN : None 942 *==========================================================================*/ 943void QCamera2HardwareInterface::debugShowPreviewFPS() 944{ 945 static int n_pFrameCount = 0; 946 static int n_pLastFrameCount = 0; 947 static nsecs_t n_pLastFpsTime = 0; 948 static float n_pFps = 0; 949 n_pFrameCount++; 950 nsecs_t now = systemTime(); 951 nsecs_t diff = now - n_pLastFpsTime; 952 if (diff > ms2ns(250)) { 953 n_pFps = ((n_pFrameCount - n_pLastFrameCount) * float(s2ns(1))) / diff; 954 ALOGE("Preview Frames Per Second: %.4f", n_pFps); 955 n_pLastFpsTime = now; 956 n_pLastFrameCount = n_pFrameCount; 957 } 958} 959 960/*=========================================================================== 961 * FUNCTION : ~QCameraCbNotifier 962 * 963 * DESCRIPTION: Destructor for exiting the callback context. 964 * 965 * PARAMETERS : None 966 * 967 * RETURN : None 968 *==========================================================================*/ 969QCameraCbNotifier::~QCameraCbNotifier() 970{ 971 mProcTh.exit(); 972} 973 974/*=========================================================================== 975 * FUNCTION : releaseNotifications 976 * 977 * DESCRIPTION: callback for releasing data stored in the callback queue. 978 * 979 * PARAMETERS : 980 * @data : data to be released 981 * @user_data : context data 982 * 983 * RETURN : None 984 *==========================================================================*/ 985void QCameraCbNotifier::releaseNotifications(void *data, void *user_data) 986{ 987 qcamera_callback_argm_t *arg = ( qcamera_callback_argm_t * ) data; 988 989 if ( ( NULL != arg ) && ( NULL != user_data ) ) { 990 991 if ( arg->release_cb ) { 992 arg->release_cb(arg->user_data, arg->cookie); 993 } 994 995 delete arg; 996 } 997} 998 999/*=========================================================================== 1000 * FUNCTION : matchSnapshotNotifications 1001 * 1002 * DESCRIPTION: matches snapshot data callbacks 1003 * 1004 * PARAMETERS : 1005 * @data : data to match 1006 * @user_data : context data 1007 * 1008 * RETURN : bool match 1009 * true - match found 1010 * false- match not found 1011 *==========================================================================*/ 1012bool QCameraCbNotifier::matchSnapshotNotifications(void *data, 1013 void */*user_data*/) 1014{ 1015 qcamera_callback_argm_t *arg = ( qcamera_callback_argm_t * ) data; 1016 if ( NULL != arg ) { 1017 if ( QCAMERA_DATA_SNAPSHOT_CALLBACK == arg->cb_type ) { 1018 return true; 1019 } 1020 } 1021 1022 return false; 1023} 1024 1025/*=========================================================================== 1026 * FUNCTION : cbNotifyRoutine 1027 * 1028 * DESCRIPTION: callback thread which interfaces with the upper layers 1029 * given input commands. 1030 * 1031 * PARAMETERS : 1032 * @data : context data 1033 * 1034 * RETURN : None 1035 *==========================================================================*/ 1036void * QCameraCbNotifier::cbNotifyRoutine(void * data) 1037{ 1038 int running = 1; 1039 int ret; 1040 QCameraCbNotifier *pme = (QCameraCbNotifier *)data; 1041 QCameraCmdThread *cmdThread = &pme->mProcTh; 1042 uint8_t isSnapshotActive = FALSE; 1043 uint32_t numOfSnapshotExpected = 0; 1044 uint32_t numOfSnapshotRcvd = 0; 1045 1046 ALOGV("%s: E", __func__); 1047 do { 1048 do { 1049 ret = cam_sem_wait(&cmdThread->cmd_sem); 1050 if (ret != 0 && errno != EINVAL) { 1051 ALOGV("%s: cam_sem_wait error (%s)", 1052 __func__, strerror(errno)); 1053 return NULL; 1054 } 1055 } while (ret != 0); 1056 1057 camera_cmd_type_t cmd = cmdThread->getCmd(); 1058 ALOGV("%s: get cmd %d", __func__, cmd); 1059 switch (cmd) { 1060 case CAMERA_CMD_TYPE_START_DATA_PROC: 1061 { 1062 isSnapshotActive = TRUE; 1063 numOfSnapshotExpected = pme->mParent->numOfSnapshotsExpected(); 1064 numOfSnapshotRcvd = 0; 1065 } 1066 break; 1067 case CAMERA_CMD_TYPE_STOP_DATA_PROC: 1068 { 1069 pme->mDataQ.flushNodes(matchSnapshotNotifications); 1070 isSnapshotActive = FALSE; 1071 1072 numOfSnapshotExpected = 0; 1073 numOfSnapshotRcvd = 0; 1074 } 1075 break; 1076 case CAMERA_CMD_TYPE_DO_NEXT_JOB: 1077 { 1078 qcamera_callback_argm_t *cb = 1079 (qcamera_callback_argm_t *)pme->mDataQ.dequeue(); 1080 if (NULL != cb) { 1081 ALOGV("%s: cb type %d received", 1082 __func__, 1083 cb->cb_type); 1084 1085 if (pme->mParent->msgTypeEnabledWithLock(cb->msg_type)) { 1086 switch (cb->cb_type) { 1087 case QCAMERA_NOTIFY_CALLBACK: 1088 { 1089 if (cb->msg_type == CAMERA_MSG_FOCUS) { 1090 ALOGD("[KPI Perf] %s : sending focus evt to app", __func__); 1091 } 1092 if (pme->mNotifyCb) { 1093 pme->mNotifyCb(cb->msg_type, 1094 cb->ext1, 1095 cb->ext2, 1096 pme->mCallbackCookie); 1097 } else { 1098 ALOGE("%s : notify callback not set!", 1099 __func__); 1100 } 1101 } 1102 break; 1103 case QCAMERA_DATA_CALLBACK: 1104 { 1105 if (pme->mDataCb) { 1106 pme->mDataCb(cb->msg_type, 1107 cb->data, 1108 cb->index, 1109 cb->metadata, 1110 pme->mCallbackCookie); 1111 } else { 1112 ALOGE("%s : data callback not set!", 1113 __func__); 1114 } 1115 } 1116 break; 1117 case QCAMERA_DATA_TIMESTAMP_CALLBACK: 1118 { 1119 if(pme->mDataCbTimestamp) { 1120 pme->mDataCbTimestamp(cb->timestamp, 1121 cb->msg_type, 1122 cb->data, 1123 cb->index, 1124 pme->mCallbackCookie); 1125 } else { 1126 ALOGE("%s:data cb with tmp not set!", 1127 __func__); 1128 } 1129 } 1130 break; 1131 case QCAMERA_DATA_SNAPSHOT_CALLBACK: 1132 { 1133 if (TRUE == isSnapshotActive && pme->mDataCb ) { 1134 pme->mDataCb(cb->msg_type, 1135 cb->data, 1136 cb->index, 1137 cb->metadata, 1138 pme->mCallbackCookie); 1139 numOfSnapshotRcvd++; 1140 if (numOfSnapshotExpected > 0 && 1141 numOfSnapshotExpected == numOfSnapshotRcvd) { 1142 // notify HWI that snapshot is done 1143 pme->mParent->processEvt(QCAMERA_SM_EVT_SNAPSHOT_DONE, 1144 NULL); 1145 } 1146 } 1147 } 1148 break; 1149 default: 1150 { 1151 ALOGE("%s : invalid cb type %d", 1152 __func__, 1153 cb->cb_type); 1154 } 1155 break; 1156 }; 1157 } else { 1158 ALOGE("%s : cb message type %d not enabled!", 1159 __func__, 1160 cb->msg_type); 1161 } 1162 if ( cb->release_cb ) { 1163 cb->release_cb(cb->user_data, cb->cookie); 1164 } 1165 delete cb; 1166 } else { 1167 ALOGE("%s: invalid cb type passed", __func__); 1168 } 1169 } 1170 break; 1171 case CAMERA_CMD_TYPE_EXIT: 1172 { 1173 pme->mDataQ.flush(); 1174 running = 0; 1175 } 1176 break; 1177 default: 1178 break; 1179 } 1180 } while (running); 1181 ALOGV("%s: X", __func__); 1182 1183 return NULL; 1184} 1185 1186/*=========================================================================== 1187 * FUNCTION : notifyCallback 1188 * 1189 * DESCRIPTION: Enqueus pending callback notifications for the upper layers. 1190 * 1191 * PARAMETERS : 1192 * @cbArgs : callback arguments 1193 * 1194 * RETURN : int32_t type of status 1195 * NO_ERROR -- success 1196 * none-zero failure code 1197 *==========================================================================*/ 1198int32_t QCameraCbNotifier::notifyCallback(qcamera_callback_argm_t &cbArgs) 1199{ 1200 qcamera_callback_argm_t *cbArg = new qcamera_callback_argm_t(); 1201 if (NULL == cbArg) { 1202 ALOGE("%s: no mem for qcamera_callback_argm_t", __func__); 1203 return NO_MEMORY; 1204 } 1205 memset(cbArg, 0, sizeof(qcamera_callback_argm_t)); 1206 *cbArg = cbArgs; 1207 1208 if (mDataQ.enqueue((void *)cbArg)) { 1209 mProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 1210 } else { 1211 ALOGE("%s: Error adding cb data into queue", __func__); 1212 delete cbArg; 1213 return UNKNOWN_ERROR; 1214 } 1215 1216 return NO_ERROR; 1217} 1218 1219/*=========================================================================== 1220 * FUNCTION : setCallbacks 1221 * 1222 * DESCRIPTION: Initializes the callback functions, which would be used for 1223 * communication with the upper layers and launches the callback 1224 * context in which the callbacks will occur. 1225 * 1226 * PARAMETERS : 1227 * @notifyCb : notification callback 1228 * @dataCb : data callback 1229 * @dataCbTimestamp : data with timestamp callback 1230 * @callbackCookie : callback context data 1231 * 1232 * RETURN : None 1233 *==========================================================================*/ 1234void QCameraCbNotifier::setCallbacks(camera_notify_callback notifyCb, 1235 camera_data_callback dataCb, 1236 camera_data_timestamp_callback dataCbTimestamp, 1237 void *callbackCookie) 1238{ 1239 if ( ( NULL == mNotifyCb ) && 1240 ( NULL == mDataCb ) && 1241 ( NULL == mDataCbTimestamp ) && 1242 ( NULL == mCallbackCookie ) ) { 1243 mNotifyCb = notifyCb; 1244 mDataCb = dataCb; 1245 mDataCbTimestamp = dataCbTimestamp; 1246 mCallbackCookie = callbackCookie; 1247 mProcTh.launch(cbNotifyRoutine, this); 1248 } else { 1249 ALOGE("%s : Camera callback notifier already initialized!", 1250 __func__); 1251 } 1252} 1253 1254/*=========================================================================== 1255 * FUNCTION : startSnapshots 1256 * 1257 * DESCRIPTION: Enables snapshot mode 1258 * 1259 * PARAMETERS : None 1260 * 1261 * RETURN : int32_t type of status 1262 * NO_ERROR -- success 1263 * none-zero failure code 1264 *==========================================================================*/ 1265int32_t QCameraCbNotifier::startSnapshots() 1266{ 1267 return mProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, TRUE); 1268} 1269 1270/*=========================================================================== 1271 * FUNCTION : stopSnapshots 1272 * 1273 * DESCRIPTION: Disables snapshot processing mode 1274 * 1275 * PARAMETERS : None 1276 * 1277 * RETURN : None 1278 *==========================================================================*/ 1279void QCameraCbNotifier::stopSnapshots() 1280{ 1281 mProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, FALSE, TRUE); 1282} 1283 1284}; // namespace qcamera 1285