QCamera2HWICallbacks.cpp revision 6f83d735d8e3b918da42e6b559fcd0efb78133e5
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 ALOGV("%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 ALOGV("%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("%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("%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("%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("%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("%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 memory->cleanCache(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 ALOGV("%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 ALOGV("%s",__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 previewMemObj->cleanCache(frame->buf_idx); 410 411 pme->dumpFrameToFile(frame->buffer, frame->frame_len, 412 frame->frame_idx, QCAMERA_DUMP_FRM_PREVIEW); 413 414 if (pme->needProcessPreviewFrame() && 415 pme->mDataCb != NULL && 416 pme->msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_FRAME) > 0 ) { 417 qcamera_callback_argm_t cbArg; 418 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 419 cbArg.cb_type = QCAMERA_DATA_CALLBACK; 420 cbArg.msg_type = CAMERA_MSG_PREVIEW_FRAME; 421 cbArg.data = preview_mem; 422 int user_data = frame->buf_idx; 423 cbArg.user_data = ( void * ) user_data; 424 cbArg.cookie = stream; 425 cbArg.release_cb = returnStreamBuffer; 426 pme->m_cbNotifier.notifyCallback(cbArg); 427 } else { 428 stream->bufDone(frame->buf_idx); 429 } 430 } 431 free(super_frame); 432} 433 434/*=========================================================================== 435 * FUNCTION : postview_stream_cb_routine 436 * 437 * DESCRIPTION: helper function to handle post frame from postview stream 438 * 439 * PARAMETERS : 440 * @super_frame : received super buffer 441 * @stream : stream object 442 * @userdata : user data ptr 443 * 444 * RETURN : None 445 * 446 * NOTE : caller passes the ownership of super_frame, it's our 447 * responsibility to free super_frame once it's done. 448 *==========================================================================*/ 449void QCamera2HardwareInterface::postview_stream_cb_routine(mm_camera_super_buf_t *super_frame, 450 QCameraStream *stream, 451 void *userdata) 452{ 453 int err = NO_ERROR; 454 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 455 QCameraGrallocMemory *memory = (QCameraGrallocMemory *)super_frame->bufs[0]->mem_info; 456 457 if (pme == NULL) { 458 ALOGE("%s: Invalid hardware object", __func__); 459 free(super_frame); 460 return; 461 } 462 if (memory == NULL) { 463 ALOGE("%s: Invalid memory object", __func__); 464 free(super_frame); 465 return; 466 } 467 468 ALOGD("%s : BEGIN", __func__); 469 470 mm_camera_buf_def_t *frame = super_frame->bufs[0]; 471 if (NULL == frame) { 472 ALOGE("%s: preview frame is NLUL", __func__); 473 free(super_frame); 474 return; 475 } 476 477 QCameraMemory *memObj = (QCameraMemory *)frame->mem_info; 478 if (NULL != memObj) { 479 memObj->cleanCache(frame->buf_idx); 480 481 pme->dumpFrameToFile(frame->buffer, frame->frame_len, 482 frame->frame_idx, QCAMERA_DUMP_FRM_THUMBNAIL); 483 } 484 485 // Display the buffer. 486 int dequeuedIdx = memory->displayBuffer(frame->buf_idx); 487 if (dequeuedIdx < 0 || dequeuedIdx >= memory->getCnt()) { 488 ALOGD("%s: Invalid dequeued buffer index %d", 489 __func__, dequeuedIdx); 490 free(super_frame); 491 return; 492 } 493 494 // Return dequeued buffer back to driver 495 err = stream->bufDone(dequeuedIdx); 496 if ( err < 0) { 497 ALOGE("stream bufDone failed %d", err); 498 } 499 500 free(super_frame); 501 ALOGD("%s : END", __func__); 502 return; 503} 504 505/*=========================================================================== 506 * FUNCTION : video_stream_cb_routine 507 * 508 * DESCRIPTION: helper function to handle video frame from video stream 509 * 510 * PARAMETERS : 511 * @super_frame : received super buffer 512 * @stream : stream object 513 * @userdata : user data ptr 514 * 515 * RETURN : None 516 * 517 * NOTE : caller passes the ownership of super_frame, it's our 518 * responsibility to free super_frame once it's done. video 519 * frame will be sent to video encoder. Once video encoder is 520 * done with the video frame, it will call another API 521 * (release_recording_frame) to return the frame back 522 *==========================================================================*/ 523void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *super_frame, 524 QCameraStream */*stream*/, 525 void *userdata) 526{ 527 ALOGV("%s : BEGIN", __func__); 528 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 529 if (pme == NULL || 530 pme->mCameraHandle == NULL || 531 pme->mCameraHandle->camera_handle != super_frame->camera_handle){ 532 ALOGE("%s: camera obj not valid", __func__); 533 // simply free super frame 534 free(super_frame); 535 return; 536 } 537 mm_camera_buf_def_t *frame = super_frame->bufs[0]; 538 539 if (pme->needDebugFps()) { 540 pme->debugShowVideoFPS(); 541 } 542 543 ALOGE("%s: Stream(%d), Timestamp: %ld %ld", 544 __func__, 545 frame->stream_id, 546 frame->ts.tv_sec, 547 frame->ts.tv_nsec); 548 549 nsecs_t timeStamp = nsecs_t(frame->ts.tv_sec) * 1000000000LL + frame->ts.tv_nsec; 550 ALOGE("Send Video frame to services/encoder TimeStamp : %lld", timeStamp); 551 QCameraMemory *videoMemObj = (QCameraMemory *)frame->mem_info; 552 camera_memory_t *video_mem = NULL; 553 if (NULL != videoMemObj) { 554 video_mem = videoMemObj->getMemory(frame->buf_idx, (pme->mStoreMetaDataInFrame > 0)? true : false); 555 } 556 if (NULL != videoMemObj && NULL != video_mem) { 557 videoMemObj->cleanCache(frame->buf_idx); 558 pme->dumpFrameToFile(frame->buffer, frame->frame_len, 559 frame->frame_idx, QCAMERA_DUMP_FRM_VIDEO); 560 if ((pme->mDataCbTimestamp != NULL) && 561 pme->msgTypeEnabledWithLock(CAMERA_MSG_VIDEO_FRAME) > 0) { 562 qcamera_callback_argm_t cbArg; 563 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); 564 cbArg.cb_type = QCAMERA_DATA_TIMESTAMP_CALLBACK; 565 cbArg.msg_type = CAMERA_MSG_VIDEO_FRAME; 566 cbArg.data = video_mem; 567 cbArg.timestamp = timeStamp; 568 pme->m_cbNotifier.notifyCallback(cbArg); 569 } 570 } 571 free(super_frame); 572 ALOGV("%s : END", __func__); 573} 574 575/*=========================================================================== 576 * FUNCTION : snapshot_stream_cb_routine 577 * 578 * DESCRIPTION: helper function to handle snapshot frame from snapshot stream 579 * 580 * PARAMETERS : 581 * @super_frame : received super buffer 582 * @stream : stream object 583 * @userdata : user data ptr 584 * 585 * RETURN : None 586 * 587 * NOTE : caller passes the ownership of super_frame, it's our 588 * responsibility to free super_frame once it's done. For 589 * snapshot, it need to send to postprocessor for jpeg 590 * encoding, therefore the ownership of super_frame will be 591 * hand to postprocessor. 592 *==========================================================================*/ 593void QCamera2HardwareInterface::snapshot_stream_cb_routine(mm_camera_super_buf_t *super_frame, 594 QCameraStream * /*stream*/, 595 void *userdata) 596{ 597 ALOGD("%s: E", __func__); 598 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 599 if (pme == NULL || 600 pme->mCameraHandle == NULL || 601 pme->mCameraHandle->camera_handle != super_frame->camera_handle){ 602 ALOGE("%s: camera obj not valid", __func__); 603 // simply free super frame 604 free(super_frame); 605 return; 606 } 607 608 pme->m_postprocessor.processData(super_frame); 609 610 ALOGD("%s: X", __func__); 611} 612 613/*=========================================================================== 614 * FUNCTION : raw_stream_cb_routine 615 * 616 * DESCRIPTION: helper function to handle raw dump frame from raw stream 617 * 618 * PARAMETERS : 619 * @super_frame : received super buffer 620 * @stream : stream object 621 * @userdata : user data ptr 622 * 623 * RETURN : None 624 * 625 * NOTE : caller passes the ownership of super_frame, it's our 626 * responsibility to free super_frame once it's done. For raw 627 * frame, there is no need to send to postprocessor for jpeg 628 * encoding. this function will play shutter and send the data 629 * callback to upper layer. Raw frame buffer will be returned 630 * back to kernel, and frame will be free after use. 631 *==========================================================================*/ 632void QCamera2HardwareInterface::raw_stream_cb_routine(mm_camera_super_buf_t * super_frame, 633 QCameraStream * /*stream*/, 634 void * userdata) 635{ 636 ALOGV("%s : BEGIN", __func__); 637 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 638 if (pme == NULL || 639 pme->mCameraHandle == NULL || 640 pme->mCameraHandle->camera_handle != super_frame->camera_handle){ 641 ALOGE("%s: camera obj not valid", __func__); 642 // simply free super frame 643 free(super_frame); 644 return; 645 } 646 647 pme->m_postprocessor.processRawData(super_frame); 648 ALOGV("%s : END", __func__); 649} 650 651/*=========================================================================== 652 * FUNCTION : metadata_stream_cb_routine 653 * 654 * DESCRIPTION: helper function to handle metadata frame from metadata stream 655 * 656 * PARAMETERS : 657 * @super_frame : received super buffer 658 * @stream : stream object 659 * @userdata : user data ptr 660 * 661 * RETURN : None 662 * 663 * NOTE : caller passes the ownership of super_frame, it's our 664 * responsibility to free super_frame once it's done. Metadata 665 * could have valid entries for face detection result or 666 * histogram statistics information. 667 *==========================================================================*/ 668void QCamera2HardwareInterface::metadata_stream_cb_routine(mm_camera_super_buf_t * super_frame, 669 QCameraStream * stream, 670 void * userdata) 671{ 672 ALOGD("%s : BEGIN", __func__); 673 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 674 if (pme == NULL || 675 pme->mCameraHandle == NULL || 676 pme->mCameraHandle->camera_handle != super_frame->camera_handle){ 677 ALOGE("%s: camera obj not valid", __func__); 678 // simply free super frame 679 free(super_frame); 680 return; 681 } 682 683 mm_camera_buf_def_t *frame = super_frame->bufs[0]; 684 cam_metadata_info_t *pMetaData = (cam_metadata_info_t *)frame->buffer; 685 686 if (pMetaData->is_faces_valid) { 687 if (pMetaData->faces_data.num_faces_detected > MAX_ROI) { 688 ALOGE("%s: Invalid number of faces %d", 689 __func__, pMetaData->faces_data.num_faces_detected); 690 } else { 691 // process face detection result 692 pme->processFaceDetectionResult(&pMetaData->faces_data); 693 } 694 } 695 696 if (pMetaData->is_stats_valid) { 697 // process histogram statistics info 698 pme->processHistogramStats(pMetaData->stats_data); 699 } 700 701 if (pMetaData->is_focus_valid) { 702 // process focus info 703 qcamera_sm_internal_evt_payload_t *payload = 704 (qcamera_sm_internal_evt_payload_t *)malloc(sizeof(qcamera_sm_internal_evt_payload_t)); 705 if (NULL != payload) { 706 memset(payload, 0, sizeof(qcamera_sm_internal_evt_payload_t)); 707 payload->evt_type = QCAMERA_INTERNAL_EVT_FOCUS_UPDATE; 708 payload->focus_data = pMetaData->focus_data; 709 int32_t rc = pme->processEvt(QCAMERA_SM_EVT_EVT_INTERNAL, payload); 710 if (rc != NO_ERROR) { 711 ALOGE("%s: processEVt failed", __func__); 712 free(payload); 713 payload = NULL; 714 715 } 716 } else { 717 ALOGE("%s: No memory for qcamera_sm_internal_evt_payload_t", __func__); 718 } 719 } 720 721 if (pMetaData->is_crop_valid) { 722 if (pMetaData->crop_data.num_of_streams > MAX_NUM_STREAMS) { 723 ALOGE("%s: Invalid num_of_streams %d in crop_data", __func__, 724 pMetaData->crop_data.num_of_streams); 725 } else { 726 pme->processZoomEvent(pMetaData->crop_data); 727 } 728 } 729 730 if (pMetaData->is_prep_snapshot_done_valid) { 731 qcamera_sm_internal_evt_payload_t *payload = 732 (qcamera_sm_internal_evt_payload_t *)malloc(sizeof(qcamera_sm_internal_evt_payload_t)); 733 if (NULL != payload) { 734 memset(payload, 0, sizeof(qcamera_sm_internal_evt_payload_t)); 735 payload->evt_type = QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE; 736 payload->prep_snapshot_state = pMetaData->prep_snapshot_done_state; 737 int32_t rc = pme->processEvt(QCAMERA_SM_EVT_EVT_INTERNAL, payload); 738 if (rc != NO_ERROR) { 739 ALOGE("%s: processEVt failed", __func__); 740 free(payload); 741 payload = NULL; 742 743 } 744 } else { 745 ALOGE("%s: No memory for qcamera_sm_internal_evt_payload_t", __func__); 746 } 747 } 748 749 stream->bufDone(frame->buf_idx); 750 free(super_frame); 751 752 ALOGD("%s : END", __func__); 753} 754 755/*=========================================================================== 756 * FUNCTION : reprocess_stream_cb_routine 757 * 758 * DESCRIPTION: helper function to handle reprocess frame from reprocess stream 759 (after reprocess, e.g., ZSL snapshot frame after WNR if 760 * WNR is enabled) 761 * 762 * PARAMETERS : 763 * @super_frame : received super buffer 764 * @stream : stream object 765 * @userdata : user data ptr 766 * 767 * RETURN : None 768 * 769 * NOTE : caller passes the ownership of super_frame, it's our 770 * responsibility to free super_frame once it's done. In this 771 * case, reprocessed frame need to be passed to postprocessor 772 * for jpeg encoding. 773 *==========================================================================*/ 774void QCamera2HardwareInterface::reprocess_stream_cb_routine(mm_camera_super_buf_t * super_frame, 775 QCameraStream * /*stream*/, 776 void * userdata) 777{ 778 ALOGV("%s: E", __func__); 779 QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata; 780 if (pme == NULL || 781 pme->mCameraHandle == NULL || 782 pme->mCameraHandle->camera_handle != super_frame->camera_handle){ 783 ALOGE("%s: camera obj not valid", __func__); 784 // simply free super frame 785 free(super_frame); 786 return; 787 } 788 789 pme->m_postprocessor.processPPData(super_frame); 790 791 ALOGV("%s: X", __func__); 792} 793 794/*=========================================================================== 795 * FUNCTION : dumpFrameToFile 796 * 797 * DESCRIPTION: helper function to dump frame into file for debug purpose. 798 * 799 * PARAMETERS : 800 * @data : data ptr 801 * @size : length of data buffer 802 * @index : identifier for data 803 * @dump_type : type of the frame to be dumped. Only such 804 * dump type is enabled, the frame will be 805 * dumped into a file. 806 * 807 * RETURN : None 808 *==========================================================================*/ 809void QCamera2HardwareInterface::dumpFrameToFile(const void *data, 810 uint32_t size, 811 int index, 812 int dump_type) 813{ 814 char value[PROPERTY_VALUE_MAX]; 815 property_get("persist.camera.dumpimg", value, "0"); 816 int32_t enabled = atoi(value); 817 int frm_num = 0; 818 uint32_t skip_mode = 0; 819 820 char buf[32]; 821 cam_dimension_t dim; 822 memset(buf, 0, sizeof(buf)); 823 memset(&dim, 0, sizeof(dim)); 824 825 if(enabled & QCAMERA_DUMP_FRM_MASK_ALL) { 826 if((enabled & dump_type) && data) { 827 frm_num = ((enabled & 0xffff0000) >> 16); 828 if(frm_num == 0) { 829 frm_num = 10; //default 10 frames 830 } 831 if(frm_num > 256) { 832 frm_num = 256; //256 buffers cycle around 833 } 834 skip_mode = ((enabled & 0x0000ff00) >> 8); 835 if(skip_mode == 0) { 836 skip_mode = 1; //no-skip 837 } 838 839 if( mDumpSkipCnt % skip_mode == 0) { 840 if((frm_num == 256) && (mDumpFrmCnt >= frm_num)) { 841 // reset frame count if cycling 842 mDumpFrmCnt = 0; 843 } 844 if (mDumpFrmCnt >= 0 && mDumpFrmCnt <= frm_num) { 845 switch (dump_type) { 846 case QCAMERA_DUMP_FRM_PREVIEW: 847 { 848 mParameters.getStreamDimension(CAM_STREAM_TYPE_PREVIEW, dim); 849 snprintf(buf, sizeof(buf), "/data/%dp_%dx%d_%d.yuv", 850 mDumpFrmCnt, dim.width, dim.height, index); 851 } 852 break; 853 case QCAMERA_DUMP_FRM_THUMBNAIL: 854 { 855 mParameters.getStreamDimension(CAM_STREAM_TYPE_POSTVIEW, dim); 856 snprintf(buf, sizeof(buf), "/data/%dt_%dx%d_%d.yuv", 857 mDumpFrmCnt, dim.width, dim.height, index); 858 } 859 break; 860 case QCAMERA_DUMP_FRM_SNAPSHOT: 861 { 862 mParameters.getStreamDimension(CAM_STREAM_TYPE_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 mParameters.getStreamDimension(CAM_STREAM_TYPE_SNAPSHOT, dim); 884 snprintf(buf, sizeof(buf), "/data/%dj_%dx%d_%d.yuv", 885 mDumpFrmCnt, dim.width, dim.height, index); 886 } 887 break; 888 default: 889 ALOGE("%s: Not supported for dumping stream type %d", 890 __func__, dump_type); 891 return; 892 } 893 894 ALOGD("dump %s size =%d, data = %p", buf, size, data); 895 int file_fd = open(buf, O_RDWR | O_CREAT, 0777); 896 if (file_fd > 0) { 897 int written_len = write(file_fd, data, size); 898 ALOGD("%s: written number of bytes %d\n", __func__, written_len); 899 close(file_fd); 900 } else { 901 ALOGE("%s: fail t open file for image dumping", __func__); 902 } 903 mDumpFrmCnt++; 904 } 905 } 906 mDumpSkipCnt++; 907 } 908 } else { 909 mDumpFrmCnt = 0; 910 } 911} 912 913/*=========================================================================== 914 * FUNCTION : debugShowVideoFPS 915 * 916 * DESCRIPTION: helper function to log video frame FPS for debug purpose. 917 * 918 * PARAMETERS : None 919 * 920 * RETURN : None 921 *==========================================================================*/ 922void QCamera2HardwareInterface::debugShowVideoFPS() 923{ 924 static int n_vFrameCount = 0; 925 static int n_vLastFrameCount = 0; 926 static nsecs_t n_vLastFpsTime = 0; 927 static float n_vFps = 0; 928 n_vFrameCount++; 929 nsecs_t now = systemTime(); 930 nsecs_t diff = now - n_vLastFpsTime; 931 if (diff > ms2ns(250)) { 932 n_vFps = ((n_vFrameCount - n_vLastFrameCount) * float(s2ns(1))) / diff; 933 ALOGE("Video Frames Per Second: %.4f", n_vFps); 934 n_vLastFpsTime = now; 935 n_vLastFrameCount = n_vFrameCount; 936 } 937} 938 939/*=========================================================================== 940 * FUNCTION : debugShowPreviewFPS 941 * 942 * DESCRIPTION: helper function to log preview frame FPS for debug purpose. 943 * 944 * PARAMETERS : None 945 * 946 * RETURN : None 947 *==========================================================================*/ 948void QCamera2HardwareInterface::debugShowPreviewFPS() 949{ 950 static int n_pFrameCount = 0; 951 static int n_pLastFrameCount = 0; 952 static nsecs_t n_pLastFpsTime = 0; 953 static float n_pFps = 0; 954 n_pFrameCount++; 955 nsecs_t now = systemTime(); 956 nsecs_t diff = now - n_pLastFpsTime; 957 if (diff > ms2ns(250)) { 958 n_pFps = ((n_pFrameCount - n_pLastFrameCount) * float(s2ns(1))) / diff; 959 ALOGE("Preview Frames Per Second: %.4f", n_pFps); 960 n_pLastFpsTime = now; 961 n_pLastFrameCount = n_pFrameCount; 962 } 963} 964 965/*=========================================================================== 966 * FUNCTION : ~QCameraCbNotifier 967 * 968 * DESCRIPTION: Destructor for exiting the callback context. 969 * 970 * PARAMETERS : None 971 * 972 * RETURN : None 973 *==========================================================================*/ 974QCameraCbNotifier::~QCameraCbNotifier() 975{ 976 mProcTh.exit(); 977} 978 979/*=========================================================================== 980 * FUNCTION : releaseNotifications 981 * 982 * DESCRIPTION: callback for releasing data stored in the callback queue. 983 * 984 * PARAMETERS : 985 * @data : data to be released 986 * @user_data : context data 987 * 988 * RETURN : None 989 *==========================================================================*/ 990void QCameraCbNotifier::releaseNotifications(void *data, void *user_data) 991{ 992 qcamera_callback_argm_t *arg = ( qcamera_callback_argm_t * ) data; 993 994 if ( ( NULL != arg ) && ( NULL != user_data ) ) { 995 996 if ( arg->release_cb ) { 997 arg->release_cb(arg->user_data, arg->cookie); 998 } 999 1000 delete arg; 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 (pme->mNotifyCb) { 1095 pme->mNotifyCb(cb->msg_type, 1096 cb->ext1, 1097 cb->ext2, 1098 pme->mCallbackCookie); 1099 } else { 1100 ALOGE("%s : notify callback not set!", 1101 __func__); 1102 } 1103 } 1104 break; 1105 case QCAMERA_DATA_CALLBACK: 1106 { 1107 if (pme->mDataCb) { 1108 pme->mDataCb(cb->msg_type, 1109 cb->data, 1110 cb->index, 1111 cb->metadata, 1112 pme->mCallbackCookie); 1113 } else { 1114 ALOGE("%s : data callback not set!", 1115 __func__); 1116 } 1117 } 1118 break; 1119 case QCAMERA_DATA_TIMESTAMP_CALLBACK: 1120 { 1121 if(pme->mDataCbTimestamp) { 1122 pme->mDataCbTimestamp(cb->timestamp, 1123 cb->msg_type, 1124 cb->data, 1125 cb->index, 1126 pme->mCallbackCookie); 1127 } else { 1128 ALOGE("%s:data cb with tmp not set!", 1129 __func__); 1130 } 1131 } 1132 break; 1133 case QCAMERA_DATA_SNAPSHOT_CALLBACK: 1134 { 1135 if (TRUE == isSnapshotActive && pme->mDataCb ) { 1136 pme->mDataCb(cb->msg_type, 1137 cb->data, 1138 cb->index, 1139 cb->metadata, 1140 pme->mCallbackCookie); 1141 numOfSnapshotRcvd++; 1142 if (numOfSnapshotExpected > 0 && 1143 numOfSnapshotExpected == numOfSnapshotRcvd) { 1144 // notify HWI that snapshot is done 1145 pme->mParent->processEvt(QCAMERA_SM_EVT_SNAPSHOT_DONE, 1146 NULL); 1147 } 1148 } 1149 } 1150 break; 1151 default: 1152 { 1153 ALOGE("%s : invalid cb type %d", 1154 __func__, 1155 cb->cb_type); 1156 } 1157 break; 1158 }; 1159 } else { 1160 ALOGE("%s : cb message type %d not enabled!", 1161 __func__, 1162 cb->msg_type); 1163 } 1164 if ( cb->release_cb ) { 1165 cb->release_cb(cb->user_data, cb->cookie); 1166 } 1167 delete cb; 1168 } else { 1169 ALOGE("%s: invalid cb type passed", __func__); 1170 } 1171 } 1172 break; 1173 case CAMERA_CMD_TYPE_EXIT: 1174 { 1175 pme->mDataQ.flush(); 1176 running = 0; 1177 } 1178 break; 1179 default: 1180 break; 1181 } 1182 } while (running); 1183 ALOGV("%s: X", __func__); 1184 1185 return NULL; 1186} 1187 1188/*=========================================================================== 1189 * FUNCTION : notifyCallback 1190 * 1191 * DESCRIPTION: Enqueus pending callback notifications for the upper layers. 1192 * 1193 * PARAMETERS : 1194 * @cbArgs : callback arguments 1195 * 1196 * RETURN : int32_t type of status 1197 * NO_ERROR -- success 1198 * none-zero failure code 1199 *==========================================================================*/ 1200int32_t QCameraCbNotifier::notifyCallback(qcamera_callback_argm_t &cbArgs) 1201{ 1202 qcamera_callback_argm_t *cbArg = new qcamera_callback_argm_t(); 1203 if (NULL == cbArg) { 1204 ALOGE("%s: no mem for qcamera_callback_argm_t", __func__); 1205 return NO_MEMORY; 1206 } 1207 memset(cbArg, 0, sizeof(qcamera_callback_argm_t)); 1208 *cbArg = cbArgs; 1209 1210 if (mDataQ.enqueue((void *)cbArg)) { 1211 mProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE); 1212 } else { 1213 ALOGE("%s: Error adding cb data into queue", __func__); 1214 delete cbArg; 1215 return UNKNOWN_ERROR; 1216 } 1217 1218 return NO_ERROR; 1219} 1220 1221/*=========================================================================== 1222 * FUNCTION : setCallbacks 1223 * 1224 * DESCRIPTION: Initializes the callback functions, which would be used for 1225 * communication with the upper layers and launches the callback 1226 * context in which the callbacks will occur. 1227 * 1228 * PARAMETERS : 1229 * @notifyCb : notification callback 1230 * @dataCb : data callback 1231 * @dataCbTimestamp : data with timestamp callback 1232 * @callbackCookie : callback context data 1233 * 1234 * RETURN : None 1235 *==========================================================================*/ 1236void QCameraCbNotifier::setCallbacks(camera_notify_callback notifyCb, 1237 camera_data_callback dataCb, 1238 camera_data_timestamp_callback dataCbTimestamp, 1239 void *callbackCookie) 1240{ 1241 if ( ( NULL == mNotifyCb ) && 1242 ( NULL == mDataCb ) && 1243 ( NULL == mDataCbTimestamp ) && 1244 ( NULL == mCallbackCookie ) ) { 1245 mNotifyCb = notifyCb; 1246 mDataCb = dataCb; 1247 mDataCbTimestamp = dataCbTimestamp; 1248 mCallbackCookie = callbackCookie; 1249 mProcTh.launch(cbNotifyRoutine, this); 1250 } else { 1251 ALOGE("%s : Camera callback notifier already initialized!", 1252 __func__); 1253 } 1254} 1255 1256/*=========================================================================== 1257 * FUNCTION : startSnapshots 1258 * 1259 * DESCRIPTION: Enables snapshot mode 1260 * 1261 * PARAMETERS : None 1262 * 1263 * RETURN : int32_t type of status 1264 * NO_ERROR -- success 1265 * none-zero failure code 1266 *==========================================================================*/ 1267int32_t QCameraCbNotifier::startSnapshots() 1268{ 1269 return mProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, TRUE); 1270} 1271 1272/*=========================================================================== 1273 * FUNCTION : stopSnapshots 1274 * 1275 * DESCRIPTION: Disables snapshot processing mode 1276 * 1277 * PARAMETERS : None 1278 * 1279 * RETURN : None 1280 *==========================================================================*/ 1281void QCameraCbNotifier::stopSnapshots() 1282{ 1283 mProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, FALSE, TRUE); 1284} 1285 1286}; // namespace qcamera 1287