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