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