ANativeWindowDisplayAdapter.cpp revision c322989ae6ff6769490828de1b5eda12b749cce9
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/GraphicBufferMapper.h> 25#include <hal_public.h> 26 27namespace android { 28 29///Constant declarations 30///@todo Check the time units 31const int ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT = 1000; // seconds 32 33//Suspends buffers after given amount of failed dq's 34const int ANativeWindowDisplayAdapter::FAILED_DQS_TO_SUSPEND = 3; 35 36 37 38OMX_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 73const 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 111const 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 */ 144ANativeWindowDisplayAdapter::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 170 mFrameWidth = 0; 171 mFrameHeight = 0; 172 mPreviewWidth = 0; 173 mPreviewHeight = 0; 174 175 mSuspend = false; 176 mFailedDQs = 0; 177 178 mPaused = false; 179 mXOff = 0; 180 mYOff = 0; 181 mFirstInit = false; 182 183 mFD = -1; 184 185 LOG_FUNCTION_NAME_EXIT; 186} 187 188ANativeWindowDisplayAdapter::~ANativeWindowDisplayAdapter() 189{ 190 Semaphore sem; 191 TIUTILS::Message msg; 192 193 LOG_FUNCTION_NAME; 194 195 ///If Frame provider exists 196 if(mFrameProvider) 197 { 198 // Unregister with the frame provider 199 mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES); 200 } 201 202 ///The ANativeWindow object will get destroyed here 203 destroy(); 204 205 ///If Display thread exists 206 if(mDisplayThread.get()) 207 { 208 ///Kill the display thread 209 sem.Create(); 210 msg.command = DisplayThread::DISPLAY_EXIT; 211 212 // Send the semaphore to signal once the command is completed 213 msg.arg1 = &sem; 214 215 ///Post the message to display thread 216 mDisplayThread->msgQ().put(&msg); 217 218 ///Wait for the ACK - implies that the thread is now started and waiting for frames 219 sem.Wait(); 220 221 // Exit and cleanup the thread 222 mDisplayThread->requestExitAndWait(); 223 224 // Delete the display thread 225 mDisplayThread.clear(); 226 } 227 228 LOG_FUNCTION_NAME_EXIT; 229 230} 231 232status_t ANativeWindowDisplayAdapter::initialize() 233{ 234 LOG_FUNCTION_NAME; 235 236 ///Create the display thread 237 mDisplayThread = new DisplayThread(this); 238 if ( !mDisplayThread.get() ) 239 { 240 CAMHAL_LOGEA("Couldn't create display thread"); 241 LOG_FUNCTION_NAME_EXIT; 242 return NO_MEMORY; 243 } 244 245 ///Start the display thread 246 status_t ret = mDisplayThread->run("DisplayThread", PRIORITY_URGENT_DISPLAY); 247 if ( ret != NO_ERROR ) 248 { 249 CAMHAL_LOGEA("Couldn't run display thread"); 250 LOG_FUNCTION_NAME_EXIT; 251 return ret; 252 } 253 254 LOG_FUNCTION_NAME_EXIT; 255 256 return ret; 257} 258 259int ANativeWindowDisplayAdapter::setPreviewWindow(preview_stream_ops_t* window) 260{ 261 LOG_FUNCTION_NAME; 262 ///Note that Display Adapter cannot work without a valid window object 263 if ( !window) 264 { 265 CAMHAL_LOGEA("NULL window object passed to DisplayAdapter"); 266 LOG_FUNCTION_NAME_EXIT; 267 return BAD_VALUE; 268 } 269 270 ///Destroy the existing window object, if it exists 271 destroy(); 272 273 ///Move to new window obj 274 mANativeWindow = window; 275 276 LOG_FUNCTION_NAME_EXIT; 277 278 return NO_ERROR; 279} 280 281int ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider) 282{ 283 LOG_FUNCTION_NAME; 284 285 // Check for NULL pointer 286 if ( !frameProvider ) 287 { 288 CAMHAL_LOGEA("NULL passed for frame provider"); 289 LOG_FUNCTION_NAME_EXIT; 290 return BAD_VALUE; 291 } 292 293 /** Dont do anything here, Just save the pointer for use when display is 294 actually enabled or disabled 295 */ 296 mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay); 297 298 LOG_FUNCTION_NAME_EXIT; 299 300 return NO_ERROR; 301} 302 303int ANativeWindowDisplayAdapter::setErrorHandler(ErrorNotifier *errorNotifier) 304{ 305 status_t ret = NO_ERROR; 306 307 LOG_FUNCTION_NAME; 308 309 if ( NULL == errorNotifier ) 310 { 311 CAMHAL_LOGEA("Invalid Error Notifier reference"); 312 ret = -EINVAL; 313 } 314 315 if ( NO_ERROR == ret ) 316 { 317 mErrorNotifier = errorNotifier; 318 } 319 320 LOG_FUNCTION_NAME_EXIT; 321 322 return ret; 323} 324 325#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 326 327status_t ANativeWindowDisplayAdapter::setSnapshotTimeRef(struct timeval *refTime) 328{ 329 status_t ret = NO_ERROR; 330 331 LOG_FUNCTION_NAME; 332 333 if ( NULL != refTime ) 334 { 335 Mutex::Autolock lock(mLock); 336 memcpy(&mStartCapture, refTime, sizeof(struct timeval)); 337 } 338 339 LOG_FUNCTION_NAME_EXIT; 340 341 return ret; 342} 343 344#endif 345 346 347int ANativeWindowDisplayAdapter::enableDisplay(int width, int height, struct timeval *refTime, S3DParameters *s3dParams) 348{ 349 Semaphore sem; 350 TIUTILS::Message msg; 351 352 LOG_FUNCTION_NAME; 353 354 if ( mDisplayEnabled ) 355 { 356 CAMHAL_LOGDA("Display is already enabled"); 357 LOG_FUNCTION_NAME_EXIT; 358 359 return NO_ERROR; 360 } 361 362#if 0 //TODO: s3d is not part of bringup...will reenable 363 if (s3dParams) 364 mOverlay->set_s3d_params(s3dParams->mode, s3dParams->framePacking, 365 s3dParams->order, s3dParams->subSampling); 366#endif 367 368#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 369 370 if ( NULL != refTime ) 371 { 372 Mutex::Autolock lock(mLock); 373 memcpy(&mStandbyToShot, refTime, sizeof(struct timeval)); 374 mMeasureStandby = true; 375 } 376 377#endif 378 379 //Send START_DISPLAY COMMAND to display thread. Display thread will start and then wait for a message 380 sem.Create(); 381 msg.command = DisplayThread::DISPLAY_START; 382 383 // Send the semaphore to signal once the command is completed 384 msg.arg1 = &sem; 385 386 ///Post the message to display thread 387 mDisplayThread->msgQ().put(&msg); 388 389 ///Wait for the ACK - implies that the thread is now started and waiting for frames 390 sem.Wait(); 391 392 // Register with the frame provider for frames 393 mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC); 394 395 mDisplayEnabled = true; 396 mPreviewWidth = width; 397 mPreviewHeight = height; 398 399 CAMHAL_LOGVB("mPreviewWidth = %d mPreviewHeight = %d", mPreviewWidth, mPreviewHeight); 400 401 LOG_FUNCTION_NAME_EXIT; 402 403 return NO_ERROR; 404} 405 406int ANativeWindowDisplayAdapter::disableDisplay() 407{ 408 LOG_FUNCTION_NAME; 409 410 if(!mDisplayEnabled) 411 { 412 CAMHAL_LOGDA("Display is already disabled"); 413 LOG_FUNCTION_NAME_EXIT; 414 return ALREADY_EXISTS; 415 } 416 417 // Unregister with the frame provider here 418 mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC); 419 420 if ( NULL != mDisplayThread.get() ) 421 { 422 //Send STOP_DISPLAY COMMAND to display thread. Display thread will stop and dequeue all messages 423 // and then wait for message 424 Semaphore sem; 425 sem.Create(); 426 TIUTILS::Message msg; 427 msg.command = DisplayThread::DISPLAY_STOP; 428 429 // Send the semaphore to signal once the command is completed 430 msg.arg1 = &sem; 431 432 ///Post the message to display thread 433 mDisplayThread->msgQ().put(&msg); 434 435 ///Wait for the ACK for display to be disabled 436 437 sem.Wait(); 438 439 } 440 441 Mutex::Autolock lock(mLock); 442 { 443 ///Reset the display enabled flag 444 mDisplayEnabled = false; 445 446 ///Reset the offset values 447 mXOff = 0; 448 mYOff = 0; 449 450 ///Reset the frame width and height values 451 mFrameWidth =0; 452 mFrameHeight = 0; 453 mPreviewWidth = 0; 454 mPreviewHeight = 0; 455 456 457 if (mANativeWindow) 458 for(unsigned int i = 0; i < mFramesWithCameraAdapterMap.size(); i++) { 459 int value = mFramesWithCameraAdapterMap.valueAt(i); 460 mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[value]); 461 } 462 else 463 LOGE("mANativeWindow is NULL"); 464 465 ///Clear the frames with camera adapter map 466 mFramesWithCameraAdapterMap.clear(); 467 } 468 LOG_FUNCTION_NAME_EXIT; 469 470 return NO_ERROR; 471} 472 473status_t ANativeWindowDisplayAdapter::pauseDisplay(bool pause) 474{ 475 status_t ret = NO_ERROR; 476 477 LOG_FUNCTION_NAME; 478 479 { 480 Mutex::Autolock lock(mLock); 481 mPaused = pause; 482 } 483 484 LOG_FUNCTION_NAME_EXIT; 485 486 return ret; 487} 488 489 490void ANativeWindowDisplayAdapter::destroy() 491{ 492 LOG_FUNCTION_NAME; 493 494 ///Check if the display is disabled, if not disable it 495 if ( mDisplayEnabled ) 496 { 497 CAMHAL_LOGDA("WARNING: Calling destroy of Display adapter when display enabled. Disabling display.."); 498 disableDisplay(); 499 } 500 501 mBufferCount = 0; 502 503 LOG_FUNCTION_NAME_EXIT; 504} 505 506// Implementation of inherited interfaces 507void* ANativeWindowDisplayAdapter::allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs) 508{ 509 LOG_FUNCTION_NAME; 510 status_t err; 511 int i = -1; 512 const int lnumBufs = numBufs; 513 int32_t *buffers = new int32_t[lnumBufs]; 514 mBufferHandleMap = new buffer_handle_t*[lnumBufs]; 515 mGrallocHandleMap = new IMG_native_handle_t*[lnumBufs]; 516 int undequeued = 0; 517 518 // Set gralloc usage bits for window. 519 err = mANativeWindow->set_usage(mANativeWindow, GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN 520 | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); 521 if (err != 0) { 522 LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 523 return NULL; 524 } 525 526 CAMHAL_LOGDB("Number of buffers set to ANativeWindow %d", numBufs); 527 //if(mBufferCount != numBufs) 528 // { 529 ///Set the number of buffers needed for camera preview 530 err = mANativeWindow->set_buffer_count(mANativeWindow, numBufs); 531 if (err != 0) { 532 LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err); 533 return NULL; 534 } 535 CAMHAL_LOGDB("Configuring %d buffers for ANativeWindow", numBufs); 536 mBufferCount = numBufs; 537 //} 538 539 // Set window geometry 540 err = mANativeWindow->set_buffers_geometry( 541 mANativeWindow, 542 width, 543 height, 544 /*toOMXPixFormat(format)*/HAL_PIXEL_FORMAT_NV12); // Gralloc only supports NV12 alloc! 545 546 if (err != 0) { 547 LOGE("native_window_set_buffers_geometry failed: %s (%d)", strerror(-err), -err); 548 return NULL; 549 } 550 551 ///We just return the buffers from ANativeWindow, if the width and height are same, else (vstab, vnf case) 552 ///re-allocate buffers using ANativeWindow and then get them 553 ///@todo - Re-allocate buffers for vnf and vstab using the width, height, format, numBufs etc 554 if ( (buffers == NULL) || (mBufferHandleMap == NULL) ) 555 { 556 CAMHAL_LOGEA("Couldn't create array for ANativeWindow buffers"); 557 LOG_FUNCTION_NAME_EXIT; 558 delete [] buffers; 559 return NULL; 560 } 561 562 mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued); 563 564 for ( i=0; i < mBufferCount; i++ ) 565 { 566 IMG_native_handle_t** hndl2hndl; 567 IMG_native_handle_t* handle; 568 int stride; // dummy variable to get stride 569 // TODO(XXX): Do we need to keep stride information in camera hal? 570 571 err = mANativeWindow->dequeue_buffer(mANativeWindow, (buffer_handle_t**) &hndl2hndl, &stride); 572 573 if (err != 0) { 574 CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 575 goto fail; 576 } 577 578 handle = *hndl2hndl; 579 580 mBufferHandleMap[i] = (buffer_handle_t*) hndl2hndl; 581 mGrallocHandleMap[i] = handle; 582 mFramesWithCameraAdapterMap.add((int) mGrallocHandleMap[i], i); 583 584 bytes = getBufSize(format, width, height); 585 586 CAMHAL_LOGDB("Adding buffer index=%d, address=0x%x", i, buffers[i]); 587 } 588 589 590 // lock the initial queueable buffers 591 for( i = 0; i < mBufferCount-undequeued; i++ ) 592 { 593 mANativeWindow->lock_buffer(mANativeWindow, mBufferHandleMap[i]); 594 } 595 596 // return the rest of the buffers back to ANativeWindow 597 for(i = (mBufferCount-undequeued); i >= 0 && i < mBufferCount; i++) 598 { 599 mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]); 600 } 601 602 mFirstInit = true; 603 mPixelFormat = getPixFormatConstant(format); 604 mFrameWidth = width; 605 mFrameHeight = height; 606 607 return mGrallocHandleMap; 608 609 fail: 610 // need to cancel buffers if any were dequeued 611 for (int start = 0; start < i && i > 0; start++) { 612 int err = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[start]); 613 if (err != 0) { 614 CAMHAL_LOGEB("cancelBuffer failed w/ error 0x%08x", err); 615 } 616 } 617 CAMHAL_LOGEA("Error occurred, performing cleanup"); 618 if ( buffers ) 619 { 620 delete [] buffers; 621 } 622 623 if ( NULL != mErrorNotifier.get() ) 624 { 625 mErrorNotifier->errorNotify(-ENOMEM); 626 } 627 628 LOG_FUNCTION_NAME_EXIT; 629 return NULL; 630 631} 632 633uint32_t * ANativeWindowDisplayAdapter::getOffsets() 634{ 635 const int lnumBufs = mBufferCount; 636 637 LOG_FUNCTION_NAME; 638 639 // TODO(XXX): Need to remove getOffsets from the API. No longer needed 640 641 if ( NULL == mANativeWindow ) 642 { 643 CAMHAL_LOGEA("mANativeWindow reference is missing"); 644 goto fail; 645 } 646 647 if( mBufferHandleMap == NULL) 648 { 649 CAMHAL_LOGEA("Buffers not allocated yet!!"); 650 goto fail; 651 } 652 653 if(mOffsetsMap == NULL) 654 { 655 mOffsetsMap = new uint32_t[lnumBufs]; 656 for(int i = 0; i < mBufferCount; i++) 657 { 658 IMG_native_handle_t* handle = (IMG_native_handle_t*) *(mBufferHandleMap[i]); 659 mOffsetsMap[i] = 0; 660 } 661 } 662 663 LOG_FUNCTION_NAME_EXIT; 664 665 return mOffsetsMap; 666 667 fail: 668 669 if ( NULL != mOffsetsMap ) 670 { 671 delete [] mOffsetsMap; 672 mOffsetsMap = NULL; 673 } 674 675 if ( NULL != mErrorNotifier.get() ) 676 { 677 mErrorNotifier->errorNotify(-ENOSYS); 678 } 679 680 LOG_FUNCTION_NAME_EXIT; 681 682 return NULL; 683} 684 685int ANativeWindowDisplayAdapter::maxQueueableBuffers(unsigned int& queueable) 686{ 687 LOG_FUNCTION_NAME; 688 int ret = NO_ERROR; 689 int undequeued = 0; 690 691 if(mBufferCount == 0) 692 { 693 ret = -ENOSYS; 694 goto end; 695 } 696 697 if(!mANativeWindow) 698 { 699 ret = -ENOSYS; 700 goto end; 701 } 702 703 mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued); 704 705 queueable = mBufferCount - undequeued; 706 707 end: 708 return ret; 709 LOG_FUNCTION_NAME_EXIT; 710} 711 712int ANativeWindowDisplayAdapter::getFd() 713{ 714 LOG_FUNCTION_NAME; 715 716 if(mFD == -1) 717 { 718 IMG_native_handle_t* handle = (IMG_native_handle_t*) *(mBufferHandleMap[0]); 719 // TODO: should we dup the fd? not really necessary and another thing for ANativeWindow 720 // to manage and close... 721 mFD = dup(handle->fd[0]); 722 } 723 724 LOG_FUNCTION_NAME_EXIT; 725 726 return mFD; 727 728} 729 730int ANativeWindowDisplayAdapter::freeBuffer(void* buf) 731{ 732 LOG_FUNCTION_NAME; 733 734 int *buffers = (int *) buf; 735 if((int *)mGrallocHandleMap != buffers) 736 { 737 CAMHAL_LOGEA("CameraHal passed wrong set of buffers to free!!!"); 738 if (mGrallocHandleMap != NULL) 739 delete []mGrallocHandleMap; 740 mGrallocHandleMap = NULL; 741 } 742 743 if ( NULL != buf ) 744 { 745 delete [] buffers; 746 } 747 748 if( mBufferHandleMap != NULL) 749 { 750 delete [] mBufferHandleMap; 751 mBufferHandleMap = NULL; 752 } 753 754 if ( NULL != mOffsetsMap ) 755 { 756 delete [] mOffsetsMap; 757 mOffsetsMap = NULL; 758 } 759 760 if( mFD != -1) 761 { 762 close(mFD); // close duped handle 763 mFD = -1; 764 } 765 766 return NO_ERROR; 767} 768 769 770bool ANativeWindowDisplayAdapter::supportsExternalBuffering() 771{ 772 return false; 773} 774 775int ANativeWindowDisplayAdapter::useBuffers(void *bufArr, int num) 776{ 777 return NO_ERROR; 778} 779 780void ANativeWindowDisplayAdapter::displayThread() 781{ 782 bool shouldLive = true; 783 int timeout = 0; 784 status_t ret; 785 786 LOG_FUNCTION_NAME; 787 788 while(shouldLive) 789 { 790 ret = TIUTILS::MessageQueue::waitForMsg(&mDisplayThread->msgQ() 791 , &mDisplayQ 792 , NULL 793 , ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT); 794 795 if ( !mDisplayThread->msgQ().isEmpty() ) 796 { 797 ///Received a message from CameraHal, process it 798 shouldLive = processHalMsg(); 799 800 } 801 else if( !mDisplayQ.isEmpty()) 802 { 803 if ( mDisplayState== ANativeWindowDisplayAdapter::DISPLAY_INIT ) 804 { 805 806 ///If display adapter is not started, continue 807 continue; 808 809 } 810 else 811 { 812 TIUTILS::Message msg; 813 ///Get the dummy msg from the displayQ 814 if(mDisplayQ.get(&msg)!=NO_ERROR) 815 { 816 CAMHAL_LOGEA("Error in getting message from display Q"); 817 continue; 818 } 819 820 // There is a frame from ANativeWindow for us to dequeue 821 // We dequeue and return the frame back to Camera adapter 822 if(mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED) 823 { 824 handleFrameReturn(); 825 } 826 827 if (mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_EXITED) 828 { 829 ///we exit the thread even though there are frames still to dequeue. They will be dequeued 830 ///in disableDisplay 831 shouldLive = false; 832 } 833 } 834 } 835 } 836 837 LOG_FUNCTION_NAME_EXIT; 838} 839 840 841bool ANativeWindowDisplayAdapter::processHalMsg() 842{ 843 TIUTILS::Message msg; 844 845 LOG_FUNCTION_NAME; 846 847 848 mDisplayThread->msgQ().get(&msg); 849 bool ret = true, invalidCommand = false; 850 851 switch ( msg.command ) 852 { 853 854 case DisplayThread::DISPLAY_START: 855 856 CAMHAL_LOGDA("Display thread received DISPLAY_START command from Camera HAL"); 857 mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STARTED; 858 859 break; 860 861 case DisplayThread::DISPLAY_STOP: 862 863 ///@bug There is no API to disable SF without destroying it 864 ///@bug Buffers might still be w/ display and will get displayed 865 ///@remarks Ideal seqyence should be something like this 866 ///mOverlay->setParameter("enabled", false); 867 CAMHAL_LOGDA("Display thread received DISPLAY_STOP command from Camera HAL"); 868 mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STOPPED; 869 870 break; 871 872 case DisplayThread::DISPLAY_EXIT: 873 874 CAMHAL_LOGDA("Display thread received DISPLAY_EXIT command from Camera HAL."); 875 CAMHAL_LOGDA("Stopping display thread..."); 876 mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_EXITED; 877 ///Note that the SF can have pending buffers when we disable the display 878 ///This is normal and the expectation is that they may not be displayed. 879 ///This is to ensure that the user experience is not impacted 880 ret = false; 881 break; 882 883 default: 884 885 CAMHAL_LOGEB("Invalid Display Thread Command 0x%x.", msg.command); 886 invalidCommand = true; 887 888 break; 889 } 890 891 ///Signal the semaphore if it is sent as part of the message 892 if ( ( msg.arg1 ) && ( !invalidCommand ) ) 893 { 894 895 CAMHAL_LOGDA("+Signalling display semaphore"); 896 Semaphore &sem = *((Semaphore*)msg.arg1); 897 898 sem.Signal(); 899 900 CAMHAL_LOGDA("-Signalling display semaphore"); 901 } 902 903 904 LOG_FUNCTION_NAME_EXIT; 905 return ret; 906} 907 908 909status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame) 910{ 911 status_t ret = NO_ERROR; 912 uint32_t actualFramesWithDisplay = 0; 913 android_native_buffer_t *buffer = NULL; 914 int i; 915 916 ///@todo Do cropping based on the stabilized frame coordinates 917 ///@todo Insert logic to drop frames here based on refresh rate of 918 ///display or rendering rate whichever is lower 919 ///Queue the buffer to overlay 920 for ( i = 0; i < mBufferCount; i++ ) 921 { 922 if ( ((int) dispFrame.mBuffer ) == (int)mGrallocHandleMap[i] ) 923 { 924 break; 925 } 926 } 927 928 if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED && 929 (!mPaused || CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) && 930 !mSuspend) 931 { 932 Mutex::Autolock lock(mLock); 933 uint32_t xOff = (dispFrame.mOffset% PAGE_SIZE); 934 uint32_t yOff = (dispFrame.mOffset / PAGE_SIZE); 935 936 // Set crop only if current x and y offsets do not match with frame offsets 937 if((mXOff!=xOff) || (mYOff!=yOff)) 938 { 939 CAMHAL_LOGDB("Offset %d xOff = %d, yOff = %d", dispFrame.mOffset, xOff, yOff); 940 uint8_t bytesPerPixel; 941 ///Calculate bytes per pixel based on the pixel format 942 if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0) 943 { 944 bytesPerPixel = 2; 945 } 946 else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0) 947 { 948 bytesPerPixel = 2; 949 } 950 else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) 951 { 952 bytesPerPixel = 1; 953 } 954 else 955 { 956 bytesPerPixel = 1; 957 } 958 959 CAMHAL_LOGVB(" crop.left = %d crop.top = %d crop.right = %d crop.bottom = %d", 960 xOff/bytesPerPixel, yOff , (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight); 961 // We'll ignore any errors here, if the surface is 962 // already invalid, we'll know soon enough. 963 mANativeWindow->set_crop(mANativeWindow, xOff/bytesPerPixel, yOff, 964 (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight); 965 966 ///Update the current x and y offsets 967 mXOff = xOff; 968 mYOff = yOff; 969 } 970 971 ret = mANativeWindow->enqueue_buffer(mANativeWindow, mBufferHandleMap[i]); 972 if (ret != 0) { 973 LOGE("Surface::queueBuffer returned error %d", ret); 974 } 975 976 mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer); 977 978 979 // HWComposer has not minimum buffer requirement. We should be able to dequeue 980 // the buffer immediately 981 TIUTILS::Message msg; 982 mDisplayQ.put(&msg); 983 984 985#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 986 987 if ( mMeasureStandby ) 988 { 989 CameraHal::PPM("Standby to first shot: Sensor Change completed - ", &mStandbyToShot); 990 mMeasureStandby = false; 991 } 992 else if (CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) 993 { 994 CameraHal::PPM("Shot to snapshot: ", &mStartCapture); 995 mShotToShot = true; 996 } 997 else if ( mShotToShot ) 998 { 999 CameraHal::PPM("Shot to shot: ", &mStartCapture); 1000 mShotToShot = false; 1001 } 1002#endif 1003 1004 } 1005 else 1006 { 1007 Mutex::Autolock lock(mLock); 1008 // cancel buffer and dequeue another one 1009 ret = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]); 1010 if (ret != 0) { 1011 LOGE("Surface::queueBuffer returned error %d", ret); 1012 } 1013 1014 mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer); 1015 1016 TIUTILS::Message msg; 1017 mDisplayQ.put(&msg); 1018 ret = NO_ERROR; 1019 } 1020 1021 return ret; 1022} 1023 1024 1025bool ANativeWindowDisplayAdapter::handleFrameReturn() 1026{ 1027 status_t err; 1028 buffer_handle_t* buf; 1029 int i = 0; 1030 int stride; // dummy variable to get stride 1031 // TODO(XXX): Do we need to keep stride information in camera hal? 1032 1033 err = mANativeWindow->dequeue_buffer(mANativeWindow, &buf, &stride); 1034 if (err != 0) { 1035 CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 1036 } 1037 1038 err = mANativeWindow->lock_buffer(mANativeWindow, buf); 1039 if (err != 0) { 1040 CAMHAL_LOGEB("lockbuffer failed: %s (%d)", strerror(-err), -err); 1041 } 1042 1043 for(i = 0; i < mBufferCount; i++) 1044 { 1045 if (mBufferHandleMap[i] == buf) 1046 break; 1047 } 1048 1049 mFramesWithCameraAdapterMap.add((int) mGrallocHandleMap[i], i); 1050 1051 CAMHAL_LOGVB("handleFrameReturn: found graphic buffer %d of %d", i, mBufferCount-1); 1052 mFrameProvider->returnFrame( (void*)mGrallocHandleMap[i], CameraFrame::PREVIEW_FRAME_SYNC); 1053 return true; 1054} 1055 1056void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame) 1057{ 1058 1059 if ( NULL != caFrame ) 1060 { 1061 if ( NULL != caFrame->mCookie ) 1062 { 1063 ANativeWindowDisplayAdapter *da = (ANativeWindowDisplayAdapter*) caFrame->mCookie; 1064 da->frameCallback(caFrame); 1065 } 1066 else 1067 { 1068 CAMHAL_LOGEB("Invalid Cookie in Camera Frame = %p, Cookie = %p", caFrame, caFrame->mCookie); 1069 } 1070 } 1071 else 1072 { 1073 CAMHAL_LOGEB("Invalid Camera Frame = %p", caFrame); 1074 } 1075 1076} 1077 1078void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame) 1079{ 1080 ///Call queueBuffer of overlay in the context of the callback thread 1081 DisplayFrame df; 1082 df.mBuffer = caFrame->mBuffer; 1083 df.mType = (CameraFrame::FrameType) caFrame->mFrameType; 1084 df.mOffset = caFrame->mOffset; 1085 df.mWidthStride = caFrame->mAlignment; 1086 df.mLength = caFrame->mLength; 1087 df.mWidth = caFrame->mWidth; 1088 df.mHeight = caFrame->mHeight; 1089 PostFrame(df); 1090} 1091 1092 1093/*--------------------ANativeWindowDisplayAdapter Class ENDS here-----------------------------*/ 1094 1095}; 1096 1097