1 /* 2 * Copyright (C) Texas Instruments - http://www.ti.com/ 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 19 20 #define LOG_TAG "CameraHAL" 21 22 #include "ANativeWindowDisplayAdapter.h" 23 #include <OMX_IVCommon.h> 24 #include <ui/GraphicBuffer.h> 25 #include <ui/GraphicBufferMapper.h> 26 #include <hal_public.h> 27 28 namespace android { 29 30 ///Constant declarations 31 ///@todo Check the time units 32 const int ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT = 1000; // seconds 33 34 //Suspends buffers after given amount of failed dq's 35 const int ANativeWindowDisplayAdapter::FAILED_DQS_TO_SUSPEND = 3; 36 37 38 OMX_COLOR_FORMATTYPE toOMXPixFormat(const char* parameters_format) 39 { 40 OMX_COLOR_FORMATTYPE pixFormat; 41 42 if ( parameters_format != NULL ) 43 { 44 if (strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0) 45 { 46 CAMHAL_LOGDA("CbYCrY format selected"); 47 pixFormat = OMX_COLOR_FormatCbYCrY; 48 } 49 else if(strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) 50 { 51 CAMHAL_LOGDA("YUV420SP format selected"); 52 pixFormat = OMX_COLOR_FormatYUV420SemiPlanar; 53 } 54 else if(strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0) 55 { 56 CAMHAL_LOGDA("RGB565 format selected"); 57 pixFormat = OMX_COLOR_Format16bitRGB565; 58 } 59 else 60 { 61 CAMHAL_LOGDA("Invalid format, CbYCrY format selected as default"); 62 pixFormat = OMX_COLOR_FormatCbYCrY; 63 } 64 } 65 else { 66 CAMHAL_LOGEA("Preview format is NULL, defaulting to CbYCrY"); 67 pixFormat = OMX_COLOR_FormatCbYCrY; 68 } 69 70 return pixFormat; 71 } 72 73 const char* getPixFormatConstant(const char* parameters_format) 74 { 75 const char* pixFormat; 76 77 if ( parameters_format != NULL ) 78 { 79 if (strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0) 80 { 81 CAMHAL_LOGVA("CbYCrY format selected"); 82 pixFormat = (const char *) CameraParameters::PIXEL_FORMAT_YUV422I; 83 } 84 else if(strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 || 85 strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_YUV420P) == 0) 86 { 87 // TODO(XXX): We are treating YV12 the same as YUV420SP 88 CAMHAL_LOGVA("YUV420SP format selected"); 89 pixFormat = (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP; 90 } 91 else if(strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0) 92 { 93 CAMHAL_LOGVA("RGB565 format selected"); 94 pixFormat = (const char *) CameraParameters::PIXEL_FORMAT_RGB565; 95 } 96 else 97 { 98 CAMHAL_LOGEA("Invalid format, CbYCrY format selected as default"); 99 pixFormat = (const char *) CameraParameters::PIXEL_FORMAT_YUV422I; 100 } 101 } 102 else 103 { 104 CAMHAL_LOGEA("Preview format is NULL, defaulting to CbYCrY"); 105 pixFormat = (const char *) CameraParameters::PIXEL_FORMAT_YUV422I; 106 } 107 108 return pixFormat; 109 } 110 111 const size_t getBufSize(const char* parameters_format, int width, int height) 112 { 113 int buf_size; 114 115 if ( parameters_format != NULL ) { 116 if (strcmp(parameters_format, 117 (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0) { 118 buf_size = width * height * 2; 119 } 120 else if((strcmp(parameters_format, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) || 121 (strcmp(parameters_format, CameraParameters::PIXEL_FORMAT_YUV420P) == 0)) { 122 buf_size = width * height * 3 / 2; 123 } 124 else if(strcmp(parameters_format, 125 (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0) { 126 buf_size = width * height * 2; 127 } else { 128 CAMHAL_LOGEA("Invalid format"); 129 buf_size = 0; 130 } 131 } else { 132 CAMHAL_LOGEA("Preview format is NULL"); 133 buf_size = 0; 134 } 135 136 return buf_size; 137 } 138 /*--------------------ANativeWindowDisplayAdapter Class STARTS here-----------------------------*/ 139 140 141 /** 142 * Display Adapter class STARTS here.. 143 */ 144 ANativeWindowDisplayAdapter::ANativeWindowDisplayAdapter():mDisplayThread(NULL), 145 mDisplayState(ANativeWindowDisplayAdapter::DISPLAY_INIT), 146 mDisplayEnabled(false), 147 mBufferCount(0) 148 149 150 151 { 152 LOG_FUNCTION_NAME; 153 154 #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 155 156 mShotToShot = false; 157 mStartCapture.tv_sec = 0; 158 mStartCapture.tv_usec = 0; 159 mStandbyToShot.tv_sec = 0; 160 mStandbyToShot.tv_usec = 0; 161 mMeasureStandby = false; 162 #endif 163 164 mPixelFormat = NULL; 165 mBufferHandleMap = NULL; 166 mGrallocHandleMap = NULL; 167 mOffsetsMap = NULL; 168 mFrameProvider = NULL; 169 mANativeWindow = NULL; 170 171 mFrameWidth = 0; 172 mFrameHeight = 0; 173 mPreviewWidth = 0; 174 mPreviewHeight = 0; 175 176 mSuspend = false; 177 mFailedDQs = 0; 178 179 mPaused = false; 180 mXOff = 0; 181 mYOff = 0; 182 mFirstInit = false; 183 184 mFD = -1; 185 186 LOG_FUNCTION_NAME_EXIT; 187 } 188 189 ANativeWindowDisplayAdapter::~ANativeWindowDisplayAdapter() 190 { 191 Semaphore sem; 192 TIUTILS::Message msg; 193 194 LOG_FUNCTION_NAME; 195 196 ///If Frame provider exists 197 if (mFrameProvider) { 198 // Unregister with the frame provider 199 mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES); 200 delete mFrameProvider; 201 mFrameProvider = NULL; 202 } 203 204 ///The ANativeWindow object will get destroyed here 205 destroy(); 206 207 ///If Display thread exists 208 if(mDisplayThread.get()) 209 { 210 ///Kill the display thread 211 sem.Create(); 212 msg.command = DisplayThread::DISPLAY_EXIT; 213 214 // Send the semaphore to signal once the command is completed 215 msg.arg1 = &sem; 216 217 ///Post the message to display thread 218 mDisplayThread->msgQ().put(&msg); 219 220 ///Wait for the ACK - implies that the thread is now started and waiting for frames 221 sem.Wait(); 222 223 // Exit and cleanup the thread 224 mDisplayThread->requestExitAndWait(); 225 226 // Delete the display thread 227 mDisplayThread.clear(); 228 } 229 230 LOG_FUNCTION_NAME_EXIT; 231 232 } 233 234 status_t ANativeWindowDisplayAdapter::initialize() 235 { 236 LOG_FUNCTION_NAME; 237 238 ///Create the display thread 239 mDisplayThread = new DisplayThread(this); 240 if ( !mDisplayThread.get() ) 241 { 242 CAMHAL_LOGEA("Couldn't create display thread"); 243 LOG_FUNCTION_NAME_EXIT; 244 return NO_MEMORY; 245 } 246 247 ///Start the display thread 248 status_t ret = mDisplayThread->run("DisplayThread", PRIORITY_URGENT_DISPLAY); 249 if ( ret != NO_ERROR ) 250 { 251 CAMHAL_LOGEA("Couldn't run display thread"); 252 LOG_FUNCTION_NAME_EXIT; 253 return ret; 254 } 255 256 LOG_FUNCTION_NAME_EXIT; 257 258 return ret; 259 } 260 261 int ANativeWindowDisplayAdapter::setPreviewWindow(preview_stream_ops_t* window) 262 { 263 LOG_FUNCTION_NAME; 264 ///Note that Display Adapter cannot work without a valid window object 265 if ( !window) 266 { 267 CAMHAL_LOGEA("NULL window object passed to DisplayAdapter"); 268 LOG_FUNCTION_NAME_EXIT; 269 return BAD_VALUE; 270 } 271 272 ///Destroy the existing window object, if it exists 273 destroy(); 274 275 ///Move to new window obj 276 mANativeWindow = window; 277 278 LOG_FUNCTION_NAME_EXIT; 279 280 return NO_ERROR; 281 } 282 283 int ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider) 284 { 285 LOG_FUNCTION_NAME; 286 287 // Check for NULL pointer 288 if ( !frameProvider ) { 289 CAMHAL_LOGEA("NULL passed for frame provider"); 290 LOG_FUNCTION_NAME_EXIT; 291 return BAD_VALUE; 292 } 293 294 //Release any previous frame providers 295 if ( NULL != mFrameProvider ) { 296 delete mFrameProvider; 297 } 298 299 /** Dont do anything here, Just save the pointer for use when display is 300 actually enabled or disabled 301 */ 302 mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay); 303 304 LOG_FUNCTION_NAME_EXIT; 305 306 return NO_ERROR; 307 } 308 309 int ANativeWindowDisplayAdapter::setErrorHandler(ErrorNotifier *errorNotifier) 310 { 311 status_t ret = NO_ERROR; 312 313 LOG_FUNCTION_NAME; 314 315 if ( NULL == errorNotifier ) 316 { 317 CAMHAL_LOGEA("Invalid Error Notifier reference"); 318 ret = -EINVAL; 319 } 320 321 if ( NO_ERROR == ret ) 322 { 323 mErrorNotifier = errorNotifier; 324 } 325 326 LOG_FUNCTION_NAME_EXIT; 327 328 return ret; 329 } 330 331 #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 332 333 status_t ANativeWindowDisplayAdapter::setSnapshotTimeRef(struct timeval *refTime) 334 { 335 status_t ret = NO_ERROR; 336 337 LOG_FUNCTION_NAME; 338 339 if ( NULL != refTime ) 340 { 341 Mutex::Autolock lock(mLock); 342 memcpy(&mStartCapture, refTime, sizeof(struct timeval)); 343 } 344 345 LOG_FUNCTION_NAME_EXIT; 346 347 return ret; 348 } 349 350 #endif 351 352 353 int ANativeWindowDisplayAdapter::enableDisplay(int width, int height, struct timeval *refTime, S3DParameters *s3dParams) 354 { 355 Semaphore sem; 356 TIUTILS::Message msg; 357 358 LOG_FUNCTION_NAME; 359 360 if ( mDisplayEnabled ) 361 { 362 CAMHAL_LOGDA("Display is already enabled"); 363 LOG_FUNCTION_NAME_EXIT; 364 365 return NO_ERROR; 366 } 367 368 #if 0 //TODO: s3d is not part of bringup...will reenable 369 if (s3dParams) 370 mOverlay->set_s3d_params(s3dParams->mode, s3dParams->framePacking, 371 s3dParams->order, s3dParams->subSampling); 372 #endif 373 374 #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 375 376 if ( NULL != refTime ) 377 { 378 Mutex::Autolock lock(mLock); 379 memcpy(&mStandbyToShot, refTime, sizeof(struct timeval)); 380 mMeasureStandby = true; 381 } 382 383 #endif 384 385 //Send START_DISPLAY COMMAND to display thread. Display thread will start and then wait for a message 386 sem.Create(); 387 msg.command = DisplayThread::DISPLAY_START; 388 389 // Send the semaphore to signal once the command is completed 390 msg.arg1 = &sem; 391 392 ///Post the message to display thread 393 mDisplayThread->msgQ().put(&msg); 394 395 ///Wait for the ACK - implies that the thread is now started and waiting for frames 396 sem.Wait(); 397 398 // Register with the frame provider for frames 399 mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC); 400 401 mDisplayEnabled = true; 402 mPreviewWidth = width; 403 mPreviewHeight = height; 404 405 CAMHAL_LOGVB("mPreviewWidth = %d mPreviewHeight = %d", mPreviewWidth, mPreviewHeight); 406 407 LOG_FUNCTION_NAME_EXIT; 408 409 return NO_ERROR; 410 } 411 412 int ANativeWindowDisplayAdapter::disableDisplay(bool cancel_buffer) 413 { 414 status_t ret = NO_ERROR; 415 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 416 417 LOG_FUNCTION_NAME; 418 419 if(!mDisplayEnabled) 420 { 421 CAMHAL_LOGDA("Display is already disabled"); 422 LOG_FUNCTION_NAME_EXIT; 423 return ALREADY_EXISTS; 424 } 425 426 // Unregister with the frame provider here 427 mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC); 428 mFrameProvider->removeFramePointers(); 429 430 if ( NULL != mDisplayThread.get() ) 431 { 432 //Send STOP_DISPLAY COMMAND to display thread. Display thread will stop and dequeue all messages 433 // and then wait for message 434 Semaphore sem; 435 sem.Create(); 436 TIUTILS::Message msg; 437 msg.command = DisplayThread::DISPLAY_STOP; 438 439 // Send the semaphore to signal once the command is completed 440 msg.arg1 = &sem; 441 442 ///Post the message to display thread 443 mDisplayThread->msgQ().put(&msg); 444 445 ///Wait for the ACK for display to be disabled 446 447 sem.Wait(); 448 449 } 450 451 Mutex::Autolock lock(mLock); 452 { 453 ///Reset the display enabled flag 454 mDisplayEnabled = false; 455 456 ///Reset the offset values 457 mXOff = 0; 458 mYOff = 0; 459 460 ///Reset the frame width and height values 461 mFrameWidth =0; 462 mFrameHeight = 0; 463 mPreviewWidth = 0; 464 mPreviewHeight = 0; 465 466 if(cancel_buffer) 467 { 468 // Return the buffers to ANativeWindow here, the mFramesWithCameraAdapterMap is also cleared inside 469 returnBuffersToWindow(); 470 } 471 else 472 { 473 mANativeWindow = NULL; 474 // Clear the frames with camera adapter map 475 mFramesWithCameraAdapterMap.clear(); 476 } 477 478 479 } 480 LOG_FUNCTION_NAME_EXIT; 481 482 return NO_ERROR; 483 } 484 485 status_t ANativeWindowDisplayAdapter::pauseDisplay(bool pause) 486 { 487 status_t ret = NO_ERROR; 488 489 LOG_FUNCTION_NAME; 490 491 { 492 Mutex::Autolock lock(mLock); 493 mPaused = pause; 494 } 495 496 LOG_FUNCTION_NAME_EXIT; 497 498 return ret; 499 } 500 501 502 void ANativeWindowDisplayAdapter::destroy() 503 { 504 LOG_FUNCTION_NAME; 505 506 ///Check if the display is disabled, if not disable it 507 if ( mDisplayEnabled ) 508 { 509 CAMHAL_LOGDA("WARNING: Calling destroy of Display adapter when display enabled. Disabling display.."); 510 disableDisplay(false); 511 } 512 513 mBufferCount = 0; 514 515 LOG_FUNCTION_NAME_EXIT; 516 } 517 518 // Implementation of inherited interfaces 519 void* ANativeWindowDisplayAdapter::allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs) 520 { 521 LOG_FUNCTION_NAME; 522 status_t err; 523 int i = -1; 524 const int lnumBufs = numBufs; 525 mBufferHandleMap = new buffer_handle_t*[lnumBufs]; 526 mGrallocHandleMap = new IMG_native_handle_t*[lnumBufs]; 527 int undequeued = 0; 528 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 529 Rect bounds; 530 531 532 if ( NULL == mANativeWindow ) { 533 return NULL; 534 } 535 536 // Set gralloc usage bits for window. 537 err = mANativeWindow->set_usage(mANativeWindow, CAMHAL_GRALLOC_USAGE); 538 if (err != 0) { 539 LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 540 541 if ( ENODEV == err ) { 542 CAMHAL_LOGEA("Preview surface abandoned!"); 543 mANativeWindow = NULL; 544 } 545 546 return NULL; 547 } 548 549 CAMHAL_LOGDB("Number of buffers set to ANativeWindow %d", numBufs); 550 ///Set the number of buffers needed for camera preview 551 err = mANativeWindow->set_buffer_count(mANativeWindow, numBufs); 552 if (err != 0) { 553 LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err); 554 555 if ( ENODEV == err ) { 556 CAMHAL_LOGEA("Preview surface abandoned!"); 557 mANativeWindow = NULL; 558 } 559 560 return NULL; 561 } 562 CAMHAL_LOGDB("Configuring %d buffers for ANativeWindow", numBufs); 563 mBufferCount = numBufs; 564 565 566 // Set window geometry 567 err = mANativeWindow->set_buffers_geometry( 568 mANativeWindow, 569 width, 570 height, 571 /*toOMXPixFormat(format)*/HAL_PIXEL_FORMAT_TI_NV12); // Gralloc only supports NV12 alloc! 572 573 if (err != 0) { 574 LOGE("native_window_set_buffers_geometry failed: %s (%d)", strerror(-err), -err); 575 576 if ( ENODEV == err ) { 577 CAMHAL_LOGEA("Preview surface abandoned!"); 578 mANativeWindow = NULL; 579 } 580 581 return NULL; 582 } 583 584 ///We just return the buffers from ANativeWindow, if the width and height are same, else (vstab, vnf case) 585 ///re-allocate buffers using ANativeWindow and then get them 586 ///@todo - Re-allocate buffers for vnf and vstab using the width, height, format, numBufs etc 587 if ( mBufferHandleMap == NULL ) 588 { 589 CAMHAL_LOGEA("Couldn't create array for ANativeWindow buffers"); 590 LOG_FUNCTION_NAME_EXIT; 591 return NULL; 592 } 593 594 mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued); 595 596 for ( i=0; i < mBufferCount; i++ ) 597 { 598 IMG_native_handle_t** hndl2hndl; 599 IMG_native_handle_t* handle; 600 int stride; // dummy variable to get stride 601 // TODO(XXX): Do we need to keep stride information in camera hal? 602 603 err = mANativeWindow->dequeue_buffer(mANativeWindow, (buffer_handle_t**) &hndl2hndl, &stride); 604 605 if (err != 0) { 606 CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 607 608 if ( ENODEV == err ) { 609 CAMHAL_LOGEA("Preview surface abandoned!"); 610 mANativeWindow = NULL; 611 } 612 613 goto fail; 614 } 615 616 handle = *hndl2hndl; 617 618 mBufferHandleMap[i] = (buffer_handle_t*) hndl2hndl; 619 mGrallocHandleMap[i] = handle; 620 mFramesWithCameraAdapterMap.add((int) mGrallocHandleMap[i], i); 621 622 bytes = getBufSize(format, width, height); 623 624 } 625 626 // lock the initial queueable buffers 627 bounds.left = 0; 628 bounds.top = 0; 629 bounds.right = width; 630 bounds.bottom = height; 631 632 for( i = 0; i < mBufferCount-undequeued; i++ ) 633 { 634 void *y_uv[2]; 635 636 mANativeWindow->lock_buffer(mANativeWindow, mBufferHandleMap[i]); 637 638 mapper.lock((buffer_handle_t) mGrallocHandleMap[i], CAMHAL_GRALLOC_USAGE, bounds, y_uv); 639 mFrameProvider->addFramePointers(mGrallocHandleMap[i] , y_uv); 640 } 641 642 // return the rest of the buffers back to ANativeWindow 643 for(i = (mBufferCount-undequeued); i >= 0 && i < mBufferCount; i++) 644 { 645 err = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]); 646 if (err != 0) { 647 CAMHAL_LOGEB("cancel_buffer failed: %s (%d)", strerror(-err), -err); 648 649 if ( ENODEV == err ) { 650 CAMHAL_LOGEA("Preview surface abandoned!"); 651 mANativeWindow = NULL; 652 } 653 654 goto fail; 655 } 656 mFramesWithCameraAdapterMap.removeItem((int) mGrallocHandleMap[i]); 657 //LOCK UNLOCK TO GET YUV POINTERS 658 void *y_uv[2]; 659 mapper.lock((buffer_handle_t) mGrallocHandleMap[i], CAMHAL_GRALLOC_USAGE, bounds, y_uv); 660 mFrameProvider->addFramePointers(mGrallocHandleMap[i] , y_uv); 661 mapper.unlock((buffer_handle_t) mGrallocHandleMap[i]); 662 } 663 664 mFirstInit = true; 665 mPixelFormat = getPixFormatConstant(format); 666 mFrameWidth = width; 667 mFrameHeight = height; 668 669 return mGrallocHandleMap; 670 671 fail: 672 // need to cancel buffers if any were dequeued 673 for (int start = 0; start < i && i > 0; start++) { 674 int err = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[start]); 675 if (err != 0) { 676 CAMHAL_LOGEB("cancelBuffer failed w/ error 0x%08x", err); 677 break; 678 } 679 mFramesWithCameraAdapterMap.removeItem((int) mGrallocHandleMap[start]); 680 } 681 682 freeBuffer(mGrallocHandleMap); 683 684 CAMHAL_LOGEA("Error occurred, performing cleanup"); 685 686 if ( NULL != mErrorNotifier.get() ) 687 { 688 mErrorNotifier->errorNotify(-ENOMEM); 689 } 690 691 LOG_FUNCTION_NAME_EXIT; 692 return NULL; 693 694 } 695 696 uint32_t * ANativeWindowDisplayAdapter::getOffsets() 697 { 698 const int lnumBufs = mBufferCount; 699 700 LOG_FUNCTION_NAME; 701 702 // TODO(XXX): Need to remove getOffsets from the API. No longer needed 703 704 if ( NULL == mANativeWindow ) 705 { 706 CAMHAL_LOGEA("mANativeWindow reference is missing"); 707 goto fail; 708 } 709 710 if( mBufferHandleMap == NULL) 711 { 712 CAMHAL_LOGEA("Buffers not allocated yet!!"); 713 goto fail; 714 } 715 716 if(mOffsetsMap == NULL) 717 { 718 mOffsetsMap = new uint32_t[lnumBufs]; 719 for(int i = 0; i < mBufferCount; i++) 720 { 721 IMG_native_handle_t* handle = (IMG_native_handle_t*) *(mBufferHandleMap[i]); 722 mOffsetsMap[i] = 0; 723 } 724 } 725 726 LOG_FUNCTION_NAME_EXIT; 727 728 return mOffsetsMap; 729 730 fail: 731 732 if ( NULL != mOffsetsMap ) 733 { 734 delete [] mOffsetsMap; 735 mOffsetsMap = NULL; 736 } 737 738 if ( NULL != mErrorNotifier.get() ) 739 { 740 mErrorNotifier->errorNotify(-ENOSYS); 741 } 742 743 LOG_FUNCTION_NAME_EXIT; 744 745 return NULL; 746 } 747 748 int ANativeWindowDisplayAdapter::maxQueueableBuffers(unsigned int& queueable) 749 { 750 LOG_FUNCTION_NAME; 751 int ret = NO_ERROR; 752 int undequeued = 0; 753 754 if(mBufferCount == 0) 755 { 756 ret = -ENOSYS; 757 goto end; 758 } 759 760 if(!mANativeWindow) 761 { 762 ret = -ENOSYS; 763 goto end; 764 } 765 766 ret = mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued); 767 if ( NO_ERROR != ret ) { 768 CAMHAL_LOGEB("get_min_undequeued_buffer_count failed: %s (%d)", strerror(-ret), -ret); 769 770 if ( ENODEV == ret ) { 771 CAMHAL_LOGEA("Preview surface abandoned!"); 772 mANativeWindow = NULL; 773 } 774 775 return -ret; 776 } 777 778 queueable = mBufferCount - undequeued; 779 780 end: 781 return ret; 782 LOG_FUNCTION_NAME_EXIT; 783 } 784 785 int ANativeWindowDisplayAdapter::getFd() 786 { 787 LOG_FUNCTION_NAME; 788 789 if(mFD == -1) 790 { 791 IMG_native_handle_t* handle = (IMG_native_handle_t*) *(mBufferHandleMap[0]); 792 // TODO: should we dup the fd? not really necessary and another thing for ANativeWindow 793 // to manage and close... 794 mFD = dup(handle->fd[0]); 795 } 796 797 LOG_FUNCTION_NAME_EXIT; 798 799 return mFD; 800 801 } 802 803 status_t ANativeWindowDisplayAdapter::returnBuffersToWindow() 804 { 805 status_t ret = NO_ERROR; 806 807 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 808 //Give the buffers back to display here - sort of free it 809 if (mANativeWindow) 810 for(unsigned int i = 0; i < mFramesWithCameraAdapterMap.size(); i++) { 811 int value = mFramesWithCameraAdapterMap.valueAt(i); 812 813 // unlock buffer before giving it up 814 mapper.unlock((buffer_handle_t) mGrallocHandleMap[value]); 815 816 ret = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[value]); 817 if ( ENODEV == ret ) { 818 CAMHAL_LOGEA("Preview surface abandoned!"); 819 mANativeWindow = NULL; 820 return -ret; 821 } else if ( NO_ERROR != ret ) { 822 CAMHAL_LOGEB("cancel_buffer() failed: %s (%d)", 823 strerror(-ret), 824 -ret); 825 return -ret; 826 } 827 } 828 else 829 LOGE("mANativeWindow is NULL"); 830 831 ///Clear the frames with camera adapter map 832 mFramesWithCameraAdapterMap.clear(); 833 834 return ret; 835 836 } 837 838 int ANativeWindowDisplayAdapter::freeBuffer(void* buf) 839 { 840 LOG_FUNCTION_NAME; 841 842 int *buffers = (int *) buf; 843 status_t ret = NO_ERROR; 844 845 Mutex::Autolock lock(mLock); 846 847 if((int *)mGrallocHandleMap != buffers) 848 { 849 CAMHAL_LOGEA("CameraHal passed wrong set of buffers to free!!!"); 850 if (mGrallocHandleMap != NULL) 851 delete []mGrallocHandleMap; 852 mGrallocHandleMap = NULL; 853 } 854 855 856 returnBuffersToWindow(); 857 858 if ( NULL != buf ) 859 { 860 delete [] buffers; 861 mGrallocHandleMap = NULL; 862 } 863 864 if( mBufferHandleMap != NULL) 865 { 866 delete [] mBufferHandleMap; 867 mBufferHandleMap = NULL; 868 } 869 870 if ( NULL != mOffsetsMap ) 871 { 872 delete [] mOffsetsMap; 873 mOffsetsMap = NULL; 874 } 875 876 if( mFD != -1) 877 { 878 close(mFD); // close duped handle 879 mFD = -1; 880 } 881 882 return NO_ERROR; 883 } 884 885 886 bool ANativeWindowDisplayAdapter::supportsExternalBuffering() 887 { 888 return false; 889 } 890 891 int ANativeWindowDisplayAdapter::useBuffers(void *bufArr, int num) 892 { 893 return NO_ERROR; 894 } 895 896 void ANativeWindowDisplayAdapter::displayThread() 897 { 898 bool shouldLive = true; 899 int timeout = 0; 900 status_t ret; 901 902 LOG_FUNCTION_NAME; 903 904 while(shouldLive) 905 { 906 ret = TIUTILS::MessageQueue::waitForMsg(&mDisplayThread->msgQ() 907 , &mDisplayQ 908 , NULL 909 , ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT); 910 911 if ( !mDisplayThread->msgQ().isEmpty() ) 912 { 913 ///Received a message from CameraHal, process it 914 shouldLive = processHalMsg(); 915 916 } 917 else if( !mDisplayQ.isEmpty()) 918 { 919 if ( mDisplayState== ANativeWindowDisplayAdapter::DISPLAY_INIT ) 920 { 921 922 ///If display adapter is not started, continue 923 continue; 924 925 } 926 else 927 { 928 TIUTILS::Message msg; 929 ///Get the dummy msg from the displayQ 930 if(mDisplayQ.get(&msg)!=NO_ERROR) 931 { 932 CAMHAL_LOGEA("Error in getting message from display Q"); 933 continue; 934 } 935 936 // There is a frame from ANativeWindow for us to dequeue 937 // We dequeue and return the frame back to Camera adapter 938 if(mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED) 939 { 940 handleFrameReturn(); 941 } 942 943 if (mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_EXITED) 944 { 945 ///we exit the thread even though there are frames still to dequeue. They will be dequeued 946 ///in disableDisplay 947 shouldLive = false; 948 } 949 } 950 } 951 } 952 953 LOG_FUNCTION_NAME_EXIT; 954 } 955 956 957 bool ANativeWindowDisplayAdapter::processHalMsg() 958 { 959 TIUTILS::Message msg; 960 961 LOG_FUNCTION_NAME; 962 963 964 mDisplayThread->msgQ().get(&msg); 965 bool ret = true, invalidCommand = false; 966 967 switch ( msg.command ) 968 { 969 970 case DisplayThread::DISPLAY_START: 971 972 CAMHAL_LOGDA("Display thread received DISPLAY_START command from Camera HAL"); 973 mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STARTED; 974 975 break; 976 977 case DisplayThread::DISPLAY_STOP: 978 979 ///@bug There is no API to disable SF without destroying it 980 ///@bug Buffers might still be w/ display and will get displayed 981 ///@remarks Ideal seqyence should be something like this 982 ///mOverlay->setParameter("enabled", false); 983 CAMHAL_LOGDA("Display thread received DISPLAY_STOP command from Camera HAL"); 984 mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STOPPED; 985 986 break; 987 988 case DisplayThread::DISPLAY_EXIT: 989 990 CAMHAL_LOGDA("Display thread received DISPLAY_EXIT command from Camera HAL."); 991 CAMHAL_LOGDA("Stopping display thread..."); 992 mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_EXITED; 993 ///Note that the SF can have pending buffers when we disable the display 994 ///This is normal and the expectation is that they may not be displayed. 995 ///This is to ensure that the user experience is not impacted 996 ret = false; 997 break; 998 999 default: 1000 1001 CAMHAL_LOGEB("Invalid Display Thread Command 0x%x.", msg.command); 1002 invalidCommand = true; 1003 1004 break; 1005 } 1006 1007 ///Signal the semaphore if it is sent as part of the message 1008 if ( ( msg.arg1 ) && ( !invalidCommand ) ) 1009 { 1010 1011 CAMHAL_LOGDA("+Signalling display semaphore"); 1012 Semaphore &sem = *((Semaphore*)msg.arg1); 1013 1014 sem.Signal(); 1015 1016 CAMHAL_LOGDA("-Signalling display semaphore"); 1017 } 1018 1019 1020 LOG_FUNCTION_NAME_EXIT; 1021 return ret; 1022 } 1023 1024 1025 status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame) 1026 { 1027 status_t ret = NO_ERROR; 1028 uint32_t actualFramesWithDisplay = 0; 1029 android_native_buffer_t *buffer = NULL; 1030 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 1031 int i; 1032 1033 ///@todo Do cropping based on the stabilized frame coordinates 1034 ///@todo Insert logic to drop frames here based on refresh rate of 1035 ///display or rendering rate whichever is lower 1036 ///Queue the buffer to overlay 1037 1038 if (!mGrallocHandleMap || !dispFrame.mBuffer) { 1039 CAMHAL_LOGEA("NULL sent to PostFrame"); 1040 return -EINVAL; 1041 } 1042 1043 for ( i = 0; i < mBufferCount; i++ ) 1044 { 1045 if ( ((int) dispFrame.mBuffer ) == (int)mGrallocHandleMap[i] ) 1046 { 1047 break; 1048 } 1049 } 1050 1051 if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED && 1052 (!mPaused || CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) && 1053 !mSuspend) 1054 { 1055 Mutex::Autolock lock(mLock); 1056 uint32_t xOff = (dispFrame.mOffset% PAGE_SIZE); 1057 uint32_t yOff = (dispFrame.mOffset / PAGE_SIZE); 1058 1059 // Set crop only if current x and y offsets do not match with frame offsets 1060 if((mXOff!=xOff) || (mYOff!=yOff)) 1061 { 1062 CAMHAL_LOGDB("Offset %d xOff = %d, yOff = %d", dispFrame.mOffset, xOff, yOff); 1063 uint8_t bytesPerPixel; 1064 ///Calculate bytes per pixel based on the pixel format 1065 if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0) 1066 { 1067 bytesPerPixel = 2; 1068 } 1069 else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0) 1070 { 1071 bytesPerPixel = 2; 1072 } 1073 else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) 1074 { 1075 bytesPerPixel = 1; 1076 } 1077 else 1078 { 1079 bytesPerPixel = 1; 1080 } 1081 1082 CAMHAL_LOGVB(" crop.left = %d crop.top = %d crop.right = %d crop.bottom = %d", 1083 xOff/bytesPerPixel, yOff , (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight); 1084 // We'll ignore any errors here, if the surface is 1085 // already invalid, we'll know soon enough. 1086 mANativeWindow->set_crop(mANativeWindow, xOff/bytesPerPixel, yOff, 1087 (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight); 1088 1089 ///Update the current x and y offsets 1090 mXOff = xOff; 1091 mYOff = yOff; 1092 } 1093 1094 // unlock buffer before sending to display 1095 mapper.unlock((buffer_handle_t) mGrallocHandleMap[i]); 1096 ret = mANativeWindow->enqueue_buffer(mANativeWindow, mBufferHandleMap[i]); 1097 if (ret != 0) { 1098 LOGE("Surface::queueBuffer returned error %d", ret); 1099 } 1100 1101 mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer); 1102 1103 1104 // HWComposer has not minimum buffer requirement. We should be able to dequeue 1105 // the buffer immediately 1106 TIUTILS::Message msg; 1107 mDisplayQ.put(&msg); 1108 1109 1110 #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 1111 1112 if ( mMeasureStandby ) 1113 { 1114 CameraHal::PPM("Standby to first shot: Sensor Change completed - ", &mStandbyToShot); 1115 mMeasureStandby = false; 1116 } 1117 else if (CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) 1118 { 1119 CameraHal::PPM("Shot to snapshot: ", &mStartCapture); 1120 mShotToShot = true; 1121 } 1122 else if ( mShotToShot ) 1123 { 1124 CameraHal::PPM("Shot to shot: ", &mStartCapture); 1125 mShotToShot = false; 1126 } 1127 #endif 1128 1129 } 1130 else 1131 { 1132 Mutex::Autolock lock(mLock); 1133 1134 // unlock buffer before giving it up 1135 mapper.unlock((buffer_handle_t) mGrallocHandleMap[i]); 1136 1137 // cancel buffer and dequeue another one 1138 ret = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]); 1139 if (ret != 0) { 1140 LOGE("Surface::queueBuffer returned error %d", ret); 1141 } 1142 1143 mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer); 1144 1145 TIUTILS::Message msg; 1146 mDisplayQ.put(&msg); 1147 ret = NO_ERROR; 1148 } 1149 1150 return ret; 1151 } 1152 1153 1154 bool ANativeWindowDisplayAdapter::handleFrameReturn() 1155 { 1156 status_t err; 1157 buffer_handle_t* buf; 1158 int i = 0; 1159 int stride; // dummy variable to get stride 1160 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 1161 Rect bounds; 1162 void *y_uv[2]; 1163 1164 // TODO(XXX): Do we need to keep stride information in camera hal? 1165 1166 if ( NULL == mANativeWindow ) { 1167 return false; 1168 } 1169 1170 err = mANativeWindow->dequeue_buffer(mANativeWindow, &buf, &stride); 1171 if (err != 0) { 1172 CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 1173 1174 if ( ENODEV == err ) { 1175 CAMHAL_LOGEA("Preview surface abandoned!"); 1176 mANativeWindow = NULL; 1177 } 1178 1179 return false; 1180 } 1181 1182 err = mANativeWindow->lock_buffer(mANativeWindow, buf); 1183 if (err != 0) { 1184 CAMHAL_LOGEB("lockbuffer failed: %s (%d)", strerror(-err), -err); 1185 1186 if ( ENODEV == err ) { 1187 CAMHAL_LOGEA("Preview surface abandoned!"); 1188 mANativeWindow = NULL; 1189 } 1190 1191 return false; 1192 } 1193 1194 for(i = 0; i < mBufferCount; i++) 1195 { 1196 if (mBufferHandleMap[i] == buf) 1197 break; 1198 } 1199 1200 // lock buffer before sending to FrameProvider for filling 1201 bounds.left = 0; 1202 bounds.top = 0; 1203 bounds.right = mFrameWidth; 1204 bounds.bottom = mFrameHeight; 1205 1206 int lock_try_count = 0; 1207 while (mapper.lock((buffer_handle_t) mGrallocHandleMap[i], CAMHAL_GRALLOC_USAGE, bounds, y_uv) < 0){ 1208 if (++lock_try_count > LOCK_BUFFER_TRIES){ 1209 if ( NULL != mErrorNotifier.get() ){ 1210 mErrorNotifier->errorNotify(CAMERA_ERROR_UNKNOWN); 1211 } 1212 return false; 1213 } 1214 CAMHAL_LOGEA("Gralloc Lock FrameReturn Error: Sleeping 15ms"); 1215 usleep(15000); 1216 } 1217 1218 mFramesWithCameraAdapterMap.add((int) mGrallocHandleMap[i], i); 1219 1220 CAMHAL_LOGVB("handleFrameReturn: found graphic buffer %d of %d", i, mBufferCount-1); 1221 mFrameProvider->returnFrame( (void*)mGrallocHandleMap[i], CameraFrame::PREVIEW_FRAME_SYNC); 1222 return true; 1223 } 1224 1225 void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame) 1226 { 1227 1228 if ( NULL != caFrame ) 1229 { 1230 if ( NULL != caFrame->mCookie ) 1231 { 1232 ANativeWindowDisplayAdapter *da = (ANativeWindowDisplayAdapter*) caFrame->mCookie; 1233 da->frameCallback(caFrame); 1234 } 1235 else 1236 { 1237 CAMHAL_LOGEB("Invalid Cookie in Camera Frame = %p, Cookie = %p", caFrame, caFrame->mCookie); 1238 } 1239 } 1240 else 1241 { 1242 CAMHAL_LOGEB("Invalid Camera Frame = %p", caFrame); 1243 } 1244 1245 } 1246 1247 void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame) 1248 { 1249 ///Call queueBuffer of overlay in the context of the callback thread 1250 DisplayFrame df; 1251 df.mBuffer = caFrame->mBuffer; 1252 df.mType = (CameraFrame::FrameType) caFrame->mFrameType; 1253 df.mOffset = caFrame->mOffset; 1254 df.mWidthStride = caFrame->mAlignment; 1255 df.mLength = caFrame->mLength; 1256 df.mWidth = caFrame->mWidth; 1257 df.mHeight = caFrame->mHeight; 1258 PostFrame(df); 1259 } 1260 1261 1262 /*--------------------ANativeWindowDisplayAdapter Class ENDS here-----------------------------*/ 1263 1264 }; 1265 1266