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