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