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