Home | History | Annotate | Download | only in camera
      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