ANativeWindowDisplayAdapter.cpp revision 2e986e5e29b391b070f608d641538c14b778d4ba
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_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); 520 if (err != 0) { 521 LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 522 return NULL; 523 } 524 525 CAMHAL_LOGDB("Number of buffers set to ANativeWindow %d", numBufs); 526 //if(mBufferCount != numBufs) 527 // { 528 ///Set the number of buffers needed for camera preview 529 err = mANativeWindow->set_buffer_count(mANativeWindow, numBufs); 530 if (err != 0) { 531 LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err); 532 return NULL; 533 } 534 CAMHAL_LOGDB("Configuring %d buffers for ANativeWindow", numBufs); 535 mBufferCount = numBufs; 536 //} 537 538 // Set window geometry 539 err = mANativeWindow->set_buffers_geometry( 540 mANativeWindow, 541 width, 542 height, 543 /*toOMXPixFormat(format)*/HAL_PIXEL_FORMAT_TI_NV12); // Gralloc only supports NV12 alloc! 544 545 if (err != 0) { 546 LOGE("native_window_set_buffers_geometry failed: %s (%d)", strerror(-err), -err); 547 return NULL; 548 } 549 550 ///We just return the buffers from ANativeWindow, if the width and height are same, else (vstab, vnf case) 551 ///re-allocate buffers using ANativeWindow and then get them 552 ///@todo - Re-allocate buffers for vnf and vstab using the width, height, format, numBufs etc 553 if ( (buffers == NULL) || (mBufferHandleMap == NULL) ) 554 { 555 CAMHAL_LOGEA("Couldn't create array for ANativeWindow buffers"); 556 LOG_FUNCTION_NAME_EXIT; 557 delete [] buffers; 558 return NULL; 559 } 560 561 mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued); 562 563 for ( i=0; i < mBufferCount; i++ ) 564 { 565 IMG_native_handle_t** hndl2hndl; 566 IMG_native_handle_t* handle; 567 int stride; // dummy variable to get stride 568 // TODO(XXX): Do we need to keep stride information in camera hal? 569 570 err = mANativeWindow->dequeue_buffer(mANativeWindow, (buffer_handle_t**) &hndl2hndl, &stride); 571 572 if (err != 0) { 573 CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 574 goto fail; 575 } 576 577 handle = *hndl2hndl; 578 579 mBufferHandleMap[i] = (buffer_handle_t*) hndl2hndl; 580 mGrallocHandleMap[i] = handle; 581 mFramesWithCameraAdapterMap.add((int) mGrallocHandleMap[i], i); 582 583 bytes = getBufSize(format, width, height); 584 585 CAMHAL_LOGDB("Adding buffer index=%d, address=0x%x", i, buffers[i]); 586 } 587 588 589 // lock the initial queueable buffers 590 for( i = 0; i < mBufferCount-undequeued; i++ ) 591 { 592 mANativeWindow->lock_buffer(mANativeWindow, mBufferHandleMap[i]); 593 } 594 595 // return the rest of the buffers back to ANativeWindow 596 for(i = (mBufferCount-undequeued); i >= 0 && i < mBufferCount; i++) 597 { 598 mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]); 599 } 600 601 mFirstInit = true; 602 mPixelFormat = getPixFormatConstant(format); 603 mFrameWidth = width; 604 mFrameHeight = height; 605 606 return mGrallocHandleMap; 607 608 fail: 609 // need to cancel buffers if any were dequeued 610 for (int start = 0; start < i && i > 0; start++) { 611 int err = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[start]); 612 if (err != 0) { 613 CAMHAL_LOGEB("cancelBuffer failed w/ error 0x%08x", err); 614 } 615 } 616 CAMHAL_LOGEA("Error occurred, performing cleanup"); 617 if ( buffers ) 618 { 619 delete [] buffers; 620 } 621 622 if ( NULL != mErrorNotifier.get() ) 623 { 624 mErrorNotifier->errorNotify(-ENOMEM); 625 } 626 627 LOG_FUNCTION_NAME_EXIT; 628 return NULL; 629 630} 631 632uint32_t * ANativeWindowDisplayAdapter::getOffsets() 633{ 634 const int lnumBufs = mBufferCount; 635 636 LOG_FUNCTION_NAME; 637 638 // TODO(XXX): Need to remove getOffsets from the API. No longer needed 639 640 if ( NULL == mANativeWindow ) 641 { 642 CAMHAL_LOGEA("mANativeWindow reference is missing"); 643 goto fail; 644 } 645 646 if( mBufferHandleMap == NULL) 647 { 648 CAMHAL_LOGEA("Buffers not allocated yet!!"); 649 goto fail; 650 } 651 652 if(mOffsetsMap == NULL) 653 { 654 mOffsetsMap = new uint32_t[lnumBufs]; 655 for(int i = 0; i < mBufferCount; i++) 656 { 657 IMG_native_handle_t* handle = (IMG_native_handle_t*) *(mBufferHandleMap[i]); 658 mOffsetsMap[i] = 0; 659 } 660 } 661 662 LOG_FUNCTION_NAME_EXIT; 663 664 return mOffsetsMap; 665 666 fail: 667 668 if ( NULL != mOffsetsMap ) 669 { 670 delete [] mOffsetsMap; 671 mOffsetsMap = NULL; 672 } 673 674 if ( NULL != mErrorNotifier.get() ) 675 { 676 mErrorNotifier->errorNotify(-ENOSYS); 677 } 678 679 LOG_FUNCTION_NAME_EXIT; 680 681 return NULL; 682} 683 684int ANativeWindowDisplayAdapter::maxQueueableBuffers(unsigned int& queueable) 685{ 686 LOG_FUNCTION_NAME; 687 int ret = NO_ERROR; 688 int undequeued = 0; 689 690 if(mBufferCount == 0) 691 { 692 ret = -ENOSYS; 693 goto end; 694 } 695 696 if(!mANativeWindow) 697 { 698 ret = -ENOSYS; 699 goto end; 700 } 701 702 mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued); 703 704 queueable = mBufferCount - undequeued; 705 706 end: 707 return ret; 708 LOG_FUNCTION_NAME_EXIT; 709} 710 711int ANativeWindowDisplayAdapter::getFd() 712{ 713 LOG_FUNCTION_NAME; 714 715 if(mFD == -1) 716 { 717 IMG_native_handle_t* handle = (IMG_native_handle_t*) *(mBufferHandleMap[0]); 718 // TODO: should we dup the fd? not really necessary and another thing for ANativeWindow 719 // to manage and close... 720 mFD = dup(handle->fd[0]); 721 } 722 723 LOG_FUNCTION_NAME_EXIT; 724 725 return mFD; 726 727} 728 729int ANativeWindowDisplayAdapter::freeBuffer(void* buf) 730{ 731 LOG_FUNCTION_NAME; 732 733 int *buffers = (int *) buf; 734 if((int *)mGrallocHandleMap != buffers) 735 { 736 CAMHAL_LOGEA("CameraHal passed wrong set of buffers to free!!!"); 737 if (mGrallocHandleMap != NULL) 738 delete []mGrallocHandleMap; 739 mGrallocHandleMap = NULL; 740 } 741 742 if ( NULL != buf ) 743 { 744 delete [] buffers; 745 } 746 747 if( mBufferHandleMap != NULL) 748 { 749 delete [] mBufferHandleMap; 750 mBufferHandleMap = NULL; 751 } 752 753 if ( NULL != mOffsetsMap ) 754 { 755 delete [] mOffsetsMap; 756 mOffsetsMap = NULL; 757 } 758 759 if( mFD != -1) 760 { 761 close(mFD); // close duped handle 762 mFD = -1; 763 } 764 765 return NO_ERROR; 766} 767 768 769bool ANativeWindowDisplayAdapter::supportsExternalBuffering() 770{ 771 return false; 772} 773 774int ANativeWindowDisplayAdapter::useBuffers(void *bufArr, int num) 775{ 776 return NO_ERROR; 777} 778 779void ANativeWindowDisplayAdapter::displayThread() 780{ 781 bool shouldLive = true; 782 int timeout = 0; 783 status_t ret; 784 785 LOG_FUNCTION_NAME; 786 787 while(shouldLive) 788 { 789 ret = TIUTILS::MessageQueue::waitForMsg(&mDisplayThread->msgQ() 790 , &mDisplayQ 791 , NULL 792 , ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT); 793 794 if ( !mDisplayThread->msgQ().isEmpty() ) 795 { 796 ///Received a message from CameraHal, process it 797 shouldLive = processHalMsg(); 798 799 } 800 else if( !mDisplayQ.isEmpty()) 801 { 802 if ( mDisplayState== ANativeWindowDisplayAdapter::DISPLAY_INIT ) 803 { 804 805 ///If display adapter is not started, continue 806 continue; 807 808 } 809 else 810 { 811 TIUTILS::Message msg; 812 ///Get the dummy msg from the displayQ 813 if(mDisplayQ.get(&msg)!=NO_ERROR) 814 { 815 CAMHAL_LOGEA("Error in getting message from display Q"); 816 continue; 817 } 818 819 // There is a frame from ANativeWindow for us to dequeue 820 // We dequeue and return the frame back to Camera adapter 821 if(mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED) 822 { 823 handleFrameReturn(); 824 } 825 826 if (mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_EXITED) 827 { 828 ///we exit the thread even though there are frames still to dequeue. They will be dequeued 829 ///in disableDisplay 830 shouldLive = false; 831 } 832 } 833 } 834 } 835 836 LOG_FUNCTION_NAME_EXIT; 837} 838 839 840bool ANativeWindowDisplayAdapter::processHalMsg() 841{ 842 TIUTILS::Message msg; 843 844 LOG_FUNCTION_NAME; 845 846 847 mDisplayThread->msgQ().get(&msg); 848 bool ret = true, invalidCommand = false; 849 850 switch ( msg.command ) 851 { 852 853 case DisplayThread::DISPLAY_START: 854 855 CAMHAL_LOGDA("Display thread received DISPLAY_START command from Camera HAL"); 856 mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STARTED; 857 858 break; 859 860 case DisplayThread::DISPLAY_STOP: 861 862 ///@bug There is no API to disable SF without destroying it 863 ///@bug Buffers might still be w/ display and will get displayed 864 ///@remarks Ideal seqyence should be something like this 865 ///mOverlay->setParameter("enabled", false); 866 CAMHAL_LOGDA("Display thread received DISPLAY_STOP command from Camera HAL"); 867 mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STOPPED; 868 869 break; 870 871 case DisplayThread::DISPLAY_EXIT: 872 873 CAMHAL_LOGDA("Display thread received DISPLAY_EXIT command from Camera HAL."); 874 CAMHAL_LOGDA("Stopping display thread..."); 875 mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_EXITED; 876 ///Note that the SF can have pending buffers when we disable the display 877 ///This is normal and the expectation is that they may not be displayed. 878 ///This is to ensure that the user experience is not impacted 879 ret = false; 880 break; 881 882 default: 883 884 CAMHAL_LOGEB("Invalid Display Thread Command 0x%x.", msg.command); 885 invalidCommand = true; 886 887 break; 888 } 889 890 ///Signal the semaphore if it is sent as part of the message 891 if ( ( msg.arg1 ) && ( !invalidCommand ) ) 892 { 893 894 CAMHAL_LOGDA("+Signalling display semaphore"); 895 Semaphore &sem = *((Semaphore*)msg.arg1); 896 897 sem.Signal(); 898 899 CAMHAL_LOGDA("-Signalling display semaphore"); 900 } 901 902 903 LOG_FUNCTION_NAME_EXIT; 904 return ret; 905} 906 907 908status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame) 909{ 910 status_t ret = NO_ERROR; 911 uint32_t actualFramesWithDisplay = 0; 912 android_native_buffer_t *buffer = NULL; 913 int i; 914 915 ///@todo Do cropping based on the stabilized frame coordinates 916 ///@todo Insert logic to drop frames here based on refresh rate of 917 ///display or rendering rate whichever is lower 918 ///Queue the buffer to overlay 919 for ( i = 0; i < mBufferCount; i++ ) 920 { 921 if ( ((int) dispFrame.mBuffer ) == (int)mGrallocHandleMap[i] ) 922 { 923 break; 924 } 925 } 926 927 if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED && 928 (!mPaused || CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) && 929 !mSuspend) 930 { 931 Mutex::Autolock lock(mLock); 932 uint32_t xOff = (dispFrame.mOffset% PAGE_SIZE); 933 uint32_t yOff = (dispFrame.mOffset / PAGE_SIZE); 934 935 // Set crop only if current x and y offsets do not match with frame offsets 936 if((mXOff!=xOff) || (mYOff!=yOff)) 937 { 938 CAMHAL_LOGDB("Offset %d xOff = %d, yOff = %d", dispFrame.mOffset, xOff, yOff); 939 uint8_t bytesPerPixel; 940 ///Calculate bytes per pixel based on the pixel format 941 if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0) 942 { 943 bytesPerPixel = 2; 944 } 945 else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0) 946 { 947 bytesPerPixel = 2; 948 } 949 else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) 950 { 951 bytesPerPixel = 1; 952 } 953 else 954 { 955 bytesPerPixel = 1; 956 } 957 958 CAMHAL_LOGVB(" crop.left = %d crop.top = %d crop.right = %d crop.bottom = %d", 959 xOff/bytesPerPixel, yOff , (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight); 960 // We'll ignore any errors here, if the surface is 961 // already invalid, we'll know soon enough. 962 mANativeWindow->set_crop(mANativeWindow, xOff/bytesPerPixel, yOff, 963 (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight); 964 965 ///Update the current x and y offsets 966 mXOff = xOff; 967 mYOff = yOff; 968 } 969 970 ret = mANativeWindow->enqueue_buffer(mANativeWindow, mBufferHandleMap[i]); 971 if (ret != 0) { 972 LOGE("Surface::queueBuffer returned error %d", ret); 973 } 974 975 mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer); 976 977 978 // HWComposer has not minimum buffer requirement. We should be able to dequeue 979 // the buffer immediately 980 TIUTILS::Message msg; 981 mDisplayQ.put(&msg); 982 983 984#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS 985 986 if ( mMeasureStandby ) 987 { 988 CameraHal::PPM("Standby to first shot: Sensor Change completed - ", &mStandbyToShot); 989 mMeasureStandby = false; 990 } 991 else if (CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) 992 { 993 CameraHal::PPM("Shot to snapshot: ", &mStartCapture); 994 mShotToShot = true; 995 } 996 else if ( mShotToShot ) 997 { 998 CameraHal::PPM("Shot to shot: ", &mStartCapture); 999 mShotToShot = false; 1000 } 1001#endif 1002 1003 } 1004 else 1005 { 1006 Mutex::Autolock lock(mLock); 1007 // cancel buffer and dequeue another one 1008 ret = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]); 1009 if (ret != 0) { 1010 LOGE("Surface::queueBuffer returned error %d", ret); 1011 } 1012 1013 mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer); 1014 1015 TIUTILS::Message msg; 1016 mDisplayQ.put(&msg); 1017 ret = NO_ERROR; 1018 } 1019 1020 return ret; 1021} 1022 1023 1024bool ANativeWindowDisplayAdapter::handleFrameReturn() 1025{ 1026 status_t err; 1027 buffer_handle_t* buf; 1028 int i = 0; 1029 int stride; // dummy variable to get stride 1030 // TODO(XXX): Do we need to keep stride information in camera hal? 1031 1032 err = mANativeWindow->dequeue_buffer(mANativeWindow, &buf, &stride); 1033 if (err != 0) { 1034 CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 1035 } 1036 1037 err = mANativeWindow->lock_buffer(mANativeWindow, buf); 1038 if (err != 0) { 1039 CAMHAL_LOGEB("lockbuffer failed: %s (%d)", strerror(-err), -err); 1040 } 1041 1042 for(i = 0; i < mBufferCount; i++) 1043 { 1044 if (mBufferHandleMap[i] == buf) 1045 break; 1046 } 1047 1048 mFramesWithCameraAdapterMap.add((int) mGrallocHandleMap[i], i); 1049 1050 CAMHAL_LOGVB("handleFrameReturn: found graphic buffer %d of %d", i, mBufferCount-1); 1051 mFrameProvider->returnFrame( (void*)mGrallocHandleMap[i], CameraFrame::PREVIEW_FRAME_SYNC); 1052 return true; 1053} 1054 1055void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame) 1056{ 1057 1058 if ( NULL != caFrame ) 1059 { 1060 if ( NULL != caFrame->mCookie ) 1061 { 1062 ANativeWindowDisplayAdapter *da = (ANativeWindowDisplayAdapter*) caFrame->mCookie; 1063 da->frameCallback(caFrame); 1064 } 1065 else 1066 { 1067 CAMHAL_LOGEB("Invalid Cookie in Camera Frame = %p, Cookie = %p", caFrame, caFrame->mCookie); 1068 } 1069 } 1070 else 1071 { 1072 CAMHAL_LOGEB("Invalid Camera Frame = %p", caFrame); 1073 } 1074 1075} 1076 1077void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame) 1078{ 1079 ///Call queueBuffer of overlay in the context of the callback thread 1080 DisplayFrame df; 1081 df.mBuffer = caFrame->mBuffer; 1082 df.mType = (CameraFrame::FrameType) caFrame->mFrameType; 1083 df.mOffset = caFrame->mOffset; 1084 df.mWidthStride = caFrame->mAlignment; 1085 df.mLength = caFrame->mLength; 1086 df.mWidth = caFrame->mWidth; 1087 df.mHeight = caFrame->mHeight; 1088 PostFrame(df); 1089} 1090 1091 1092/*--------------------ANativeWindowDisplayAdapter Class ENDS here-----------------------------*/ 1093 1094}; 1095 1096