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 
     23 #include "CameraHal.h"
     24 #include "VideoMetadata.h"
     25 #include "Encoder_libjpeg.h"
     26 #include <MetadataBufferType.h>
     27 #include <ui/GraphicBuffer.h>
     28 #include <ui/GraphicBufferMapper.h>
     29 #include "NV12_resize.h"
     30 
     31 namespace android {
     32 
     33 const int AppCallbackNotifier::NOTIFIER_TIMEOUT = -1;
     34 KeyedVector<void*, sp<Encoder_libjpeg> > gEncoderQueue;
     35 
     36 void AppCallbackNotifierEncoderCallback(void* main_jpeg,
     37                                         void* thumb_jpeg,
     38                                         CameraFrame::FrameType type,
     39                                         void* cookie1,
     40                                         void* cookie2,
     41                                         void* cookie3)
     42 {
     43     if (cookie1) {
     44         AppCallbackNotifier* cb = (AppCallbackNotifier*) cookie1;
     45         cb->EncoderDoneCb(main_jpeg, thumb_jpeg, type, cookie2, cookie3);
     46     }
     47 }
     48 
     49 /*--------------------NotificationHandler Class STARTS here-----------------------------*/
     50 
     51 void AppCallbackNotifier::EncoderDoneCb(void* main_jpeg, void* thumb_jpeg, CameraFrame::FrameType type, void* cookie1, void* cookie2)
     52 {
     53     camera_memory_t* encoded_mem = NULL;
     54     Encoder_libjpeg::params *main_param = NULL, *thumb_param = NULL;
     55     size_t jpeg_size;
     56     uint8_t* src = NULL;
     57     sp<Encoder_libjpeg> encoder = NULL;
     58 
     59     LOG_FUNCTION_NAME;
     60 
     61     camera_memory_t* picture = NULL;
     62 
     63     {
     64     Mutex::Autolock lock(mLock);
     65 
     66     if (!main_jpeg) {
     67         goto exit;
     68     }
     69 
     70     encoded_mem = (camera_memory_t*) cookie1;
     71     main_param = (Encoder_libjpeg::params *) main_jpeg;
     72     jpeg_size = main_param->jpeg_size;
     73     src = main_param->src;
     74 
     75     if(encoded_mem && encoded_mem->data && (jpeg_size > 0)) {
     76         if (cookie2) {
     77             ExifElementsTable* exif = (ExifElementsTable*) cookie2;
     78             Section_t* exif_section = NULL;
     79 
     80             exif->insertExifToJpeg((unsigned char*) encoded_mem->data, jpeg_size);
     81 
     82             if(thumb_jpeg) {
     83                 thumb_param = (Encoder_libjpeg::params *) thumb_jpeg;
     84                 exif->insertExifThumbnailImage((const char*)thumb_param->dst,
     85                                                (int)thumb_param->jpeg_size);
     86             }
     87 
     88             exif_section = FindSection(M_EXIF);
     89 
     90             if (exif_section) {
     91                 picture = mRequestMemory(-1, jpeg_size + exif_section->Size, 1, NULL);
     92                 if (picture && picture->data) {
     93                     exif->saveJpeg((unsigned char*) picture->data, jpeg_size + exif_section->Size);
     94                 }
     95             }
     96             delete exif;
     97             cookie2 = NULL;
     98         } else {
     99             picture = mRequestMemory(-1, jpeg_size, 1, NULL);
    100             if (picture && picture->data) {
    101                 memcpy(picture->data, encoded_mem->data, jpeg_size);
    102             }
    103         }
    104     }
    105     } // scope for mutex lock
    106 
    107     if (!mRawAvailable) {
    108         dummyRaw();
    109     } else {
    110         mRawAvailable = false;
    111     }
    112 
    113     // Send the callback to the application only if the notifier is started and the message is enabled
    114     if(picture && (mNotifierState==AppCallbackNotifier::NOTIFIER_STARTED) &&
    115                   (mCameraHal->msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE)))
    116     {
    117         Mutex::Autolock lock(mBurstLock);
    118 #if 0 //TODO: enable burst mode later
    119         if ( mBurst )
    120         {
    121             `(CAMERA_MSG_BURST_IMAGE, JPEGPictureMemBase, mCallbackCookie);
    122         }
    123         else
    124 #endif
    125         {
    126             mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, picture, 0, NULL, mCallbackCookie);
    127         }
    128     }
    129 
    130  exit:
    131 
    132     if (main_jpeg) {
    133         free(main_jpeg);
    134     }
    135 
    136     if (thumb_jpeg) {
    137        if (((Encoder_libjpeg::params *) thumb_jpeg)->dst) {
    138            free(((Encoder_libjpeg::params *) thumb_jpeg)->dst);
    139        }
    140        free(thumb_jpeg);
    141     }
    142 
    143     if (encoded_mem) {
    144         encoded_mem->release(encoded_mem);
    145     }
    146 
    147     if (picture) {
    148         picture->release(picture);
    149     }
    150 
    151     if (cookie2) {
    152         delete (ExifElementsTable*) cookie2;
    153     }
    154 
    155     if (mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) {
    156         encoder = gEncoderQueue.valueFor(src);
    157         if (encoder.get()) {
    158             gEncoderQueue.removeItem(src);
    159             encoder.clear();
    160         }
    161         mFrameProvider->returnFrame(src, type);
    162     }
    163 
    164     LOG_FUNCTION_NAME_EXIT;
    165 }
    166 
    167 /**
    168   * NotificationHandler class
    169   */
    170 
    171 ///Initialization function for AppCallbackNotifier
    172 status_t AppCallbackNotifier::initialize()
    173 {
    174     LOG_FUNCTION_NAME;
    175 
    176     mMeasurementEnabled = false;
    177 
    178     ///Create the app notifier thread
    179     mNotificationThread = new NotificationThread(this);
    180     if(!mNotificationThread.get())
    181         {
    182         CAMHAL_LOGEA("Couldn't create Notification thread");
    183         return NO_MEMORY;
    184         }
    185 
    186     ///Start the display thread
    187     status_t ret = mNotificationThread->run("NotificationThread", PRIORITY_URGENT_DISPLAY);
    188     if(ret!=NO_ERROR)
    189         {
    190         CAMHAL_LOGEA("Couldn't run NotificationThread");
    191         mNotificationThread.clear();
    192         return ret;
    193         }
    194 
    195     mUseMetaDataBufferMode = true;
    196     mRawAvailable = false;
    197 
    198     LOG_FUNCTION_NAME_EXIT;
    199 
    200     return ret;
    201 }
    202 
    203 void AppCallbackNotifier::setCallbacks(CameraHal* cameraHal,
    204                                         camera_notify_callback notify_cb,
    205                                         camera_data_callback data_cb,
    206                                         camera_data_timestamp_callback data_cb_timestamp,
    207                                         camera_request_memory get_memory,
    208                                         void *user)
    209 {
    210     Mutex::Autolock lock(mLock);
    211 
    212     LOG_FUNCTION_NAME;
    213 
    214     mCameraHal = cameraHal;
    215     mNotifyCb = notify_cb;
    216     mDataCb = data_cb;
    217     mDataCbTimestamp = data_cb_timestamp;
    218     mRequestMemory = get_memory;
    219     mCallbackCookie = user;
    220 
    221     LOG_FUNCTION_NAME_EXIT;
    222 }
    223 
    224 void AppCallbackNotifier::setMeasurements(bool enable)
    225 {
    226     Mutex::Autolock lock(mLock);
    227 
    228     LOG_FUNCTION_NAME;
    229 
    230     mMeasurementEnabled = enable;
    231 
    232     if (  enable  )
    233         {
    234          mFrameProvider->enableFrameNotification(CameraFrame::FRAME_DATA_SYNC);
    235         }
    236 
    237     LOG_FUNCTION_NAME_EXIT;
    238 }
    239 
    240 
    241 //All sub-components of Camera HAL call this whenever any error happens
    242 void AppCallbackNotifier::errorNotify(int error)
    243 {
    244     LOG_FUNCTION_NAME;
    245 
    246     CAMHAL_LOGEB("AppCallbackNotifier received error %d", error);
    247 
    248     // If it is a fatal error abort here!
    249     if((error == CAMERA_ERROR_FATAL) || (error == CAMERA_ERROR_HARD)) {
    250         //We kill media server if we encounter these errors as there is
    251         //no point continuing and apps also don't handle errors other
    252         //than media server death always.
    253         abort();
    254         return;
    255     }
    256 
    257     if (  ( NULL != mCameraHal ) &&
    258           ( NULL != mNotifyCb ) &&
    259           ( mCameraHal->msgTypeEnabled(CAMERA_MSG_ERROR) ) )
    260       {
    261         CAMHAL_LOGEB("AppCallbackNotifier mNotifyCb %d", error);
    262         mNotifyCb(CAMERA_MSG_ERROR, CAMERA_ERROR_UNKNOWN, 0, mCallbackCookie);
    263       }
    264 
    265     LOG_FUNCTION_NAME_EXIT;
    266 }
    267 
    268 bool AppCallbackNotifier::notificationThread()
    269 {
    270     bool shouldLive = true;
    271     status_t ret;
    272 
    273     LOG_FUNCTION_NAME;
    274 
    275     //CAMHAL_LOGDA("Notification Thread waiting for message");
    276     ret = TIUTILS::MessageQueue::waitForMsg(&mNotificationThread->msgQ(),
    277                                             &mEventQ,
    278                                             &mFrameQ,
    279                                             AppCallbackNotifier::NOTIFIER_TIMEOUT);
    280 
    281     //CAMHAL_LOGDA("Notification Thread received message");
    282 
    283     if (mNotificationThread->msgQ().hasMsg()) {
    284         ///Received a message from CameraHal, process it
    285         CAMHAL_LOGDA("Notification Thread received message from Camera HAL");
    286         shouldLive = processMessage();
    287         if(!shouldLive) {
    288                 CAMHAL_LOGDA("Notification Thread exiting.");
    289         }
    290     }
    291 
    292     if(mEventQ.hasMsg()) {
    293         ///Received an event from one of the event providers
    294         CAMHAL_LOGDA("Notification Thread received an event from event provider (CameraAdapter)");
    295         notifyEvent();
    296      }
    297 
    298     if(mFrameQ.hasMsg()) {
    299        ///Received a frame from one of the frame providers
    300        //CAMHAL_LOGDA("Notification Thread received a frame from frame provider (CameraAdapter)");
    301        notifyFrame();
    302     }
    303 
    304     LOG_FUNCTION_NAME_EXIT;
    305     return shouldLive;
    306 }
    307 
    308 void AppCallbackNotifier::notifyEvent()
    309 {
    310     ///Receive and send the event notifications to app
    311     TIUTILS::Message msg;
    312     LOG_FUNCTION_NAME;
    313     {
    314     Mutex::Autolock lock(mLock);
    315     mEventQ.get(&msg);
    316     }
    317     bool ret = true;
    318     CameraHalEvent *evt = NULL;
    319     CameraHalEvent::FocusEventData *focusEvtData;
    320     CameraHalEvent::ZoomEventData *zoomEvtData;
    321     CameraHalEvent::FaceEventData faceEvtData;
    322 
    323     if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED)
    324     {
    325         return;
    326     }
    327 
    328     switch(msg.command)
    329         {
    330         case AppCallbackNotifier::NOTIFIER_CMD_PROCESS_EVENT:
    331 
    332             evt = ( CameraHalEvent * ) msg.arg1;
    333 
    334             if ( NULL == evt )
    335                 {
    336                 CAMHAL_LOGEA("Invalid CameraHalEvent");
    337                 return;
    338                 }
    339 
    340             switch(evt->mEventType)
    341                 {
    342                 case CameraHalEvent::EVENT_SHUTTER:
    343 
    344                     if ( ( NULL != mCameraHal ) &&
    345                           ( NULL != mNotifyCb ) &&
    346                           ( mCameraHal->msgTypeEnabled(CAMERA_MSG_SHUTTER) ) )
    347                         {
    348                             mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
    349                         }
    350                     mRawAvailable = false;
    351 
    352                     break;
    353 
    354                 case CameraHalEvent::EVENT_FOCUS_LOCKED:
    355                 case CameraHalEvent::EVENT_FOCUS_ERROR:
    356 
    357                     focusEvtData = &evt->mEventData->focusEvent;
    358                     if ( ( focusEvtData->focusLocked ) &&
    359                           ( NULL != mCameraHal ) &&
    360                           ( NULL != mNotifyCb ) &&
    361                           ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS) ) )
    362                         {
    363                          mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
    364                          mCameraHal->disableMsgType(CAMERA_MSG_FOCUS);
    365                         }
    366                     else if ( focusEvtData->focusError &&
    367                                 ( NULL != mCameraHal ) &&
    368                                 ( NULL != mNotifyCb ) &&
    369                                 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS) ) )
    370                         {
    371                          mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie);
    372                          mCameraHal->disableMsgType(CAMERA_MSG_FOCUS);
    373                         }
    374 
    375                     break;
    376 
    377                 case CameraHalEvent::EVENT_ZOOM_INDEX_REACHED:
    378 
    379                     zoomEvtData = &evt->mEventData->zoomEvent;
    380 
    381                     if ( ( NULL != mCameraHal ) &&
    382                          ( NULL != mNotifyCb) &&
    383                          ( mCameraHal->msgTypeEnabled(CAMERA_MSG_ZOOM) ) )
    384                         {
    385                         mNotifyCb(CAMERA_MSG_ZOOM, zoomEvtData->currentZoomIndex, zoomEvtData->targetZoomIndexReached, mCallbackCookie);
    386                         }
    387 
    388                     break;
    389 
    390                 case CameraHalEvent::EVENT_FACE:
    391 
    392                     faceEvtData = evt->mEventData->faceEvent;
    393 
    394                     if ( ( NULL != mCameraHal ) &&
    395                          ( NULL != mNotifyCb) &&
    396                          ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_METADATA) ) )
    397                         {
    398                         // WA for an issue inside CameraService
    399                         camera_memory_t *tmpBuffer = mRequestMemory(-1, 1, 1, NULL);
    400 
    401                         mDataCb(CAMERA_MSG_PREVIEW_METADATA,
    402                                 tmpBuffer,
    403                                 0,
    404                                 faceEvtData->getFaceResult(),
    405                                 mCallbackCookie);
    406 
    407                         faceEvtData.clear();
    408 
    409                         if ( NULL != tmpBuffer ) {
    410                             tmpBuffer->release(tmpBuffer);
    411                         }
    412 
    413                         }
    414 
    415                     break;
    416 
    417                 case CameraHalEvent::ALL_EVENTS:
    418                     break;
    419                 default:
    420                     break;
    421                 }
    422 
    423             break;
    424         }
    425 
    426     if ( NULL != evt )
    427         {
    428         delete evt;
    429         }
    430 
    431 
    432     LOG_FUNCTION_NAME_EXIT;
    433 
    434 }
    435 
    436 static void copy2Dto1D(void *dst,
    437                        void *src,
    438                        int width,
    439                        int height,
    440                        size_t stride,
    441                        uint32_t offset,
    442                        unsigned int bytesPerPixel,
    443                        size_t length,
    444                        const char *pixelFormat)
    445 {
    446     unsigned int alignedRow, row;
    447     unsigned char *bufferDst, *bufferSrc;
    448     unsigned char *bufferDstEnd, *bufferSrcEnd;
    449     uint16_t *bufferSrc_UV;
    450 
    451     unsigned int *y_uv = (unsigned int *)src;
    452 
    453     CAMHAL_LOGVB("copy2Dto1D() y= %p ; uv=%p.",y_uv[0], y_uv[1]);
    454     CAMHAL_LOGVB("pixelFormat,= %d; offset=%d",*pixelFormat,offset);
    455 
    456     if (pixelFormat!=NULL) {
    457         if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
    458             bytesPerPixel = 2;
    459         } else if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ||
    460                    strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) {
    461             bytesPerPixel = 1;
    462             bufferDst = ( unsigned char * ) dst;
    463             bufferDstEnd = ( unsigned char * ) dst + width*height*bytesPerPixel;
    464             bufferSrc = ( unsigned char * ) y_uv[0] + offset;
    465             bufferSrcEnd = ( unsigned char * ) ( ( size_t ) y_uv[0] + length + offset);
    466             row = width*bytesPerPixel;
    467             alignedRow = stride-width;
    468             int stride_bytes = stride / 8;
    469             uint32_t xOff = offset % stride;
    470             uint32_t yOff = offset / stride;
    471 
    472             // going to convert from NV12 here and return
    473             // Step 1: Y plane: iterate through each row and copy
    474             for ( int i = 0 ; i < height ; i++) {
    475                 memcpy(bufferDst, bufferSrc, row);
    476                 bufferSrc += stride;
    477                 bufferDst += row;
    478                 if ( ( bufferSrc > bufferSrcEnd ) || ( bufferDst > bufferDstEnd ) ) {
    479                     break;
    480                 }
    481             }
    482 
    483             bufferSrc_UV = ( uint16_t * ) ((uint8_t*)y_uv[1] + (stride/2)*yOff + xOff);
    484 
    485             if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
    486                  uint16_t *bufferDst_UV;
    487 
    488                 // Step 2: UV plane: convert NV12 to NV21 by swapping U & V
    489                 bufferDst_UV = (uint16_t *) (((uint8_t*)dst)+row*height);
    490 
    491                 for (int i = 0 ; i < height/2 ; i++, bufferSrc_UV += alignedRow/2) {
    492                     int n = width;
    493                     asm volatile (
    494                     "   pld [%[src], %[src_stride], lsl #2]                         \n\t"
    495                     "   cmp %[n], #32                                               \n\t"
    496                     "   blt 1f                                                      \n\t"
    497                     "0: @ 32 byte swap                                              \n\t"
    498                     "   sub %[n], %[n], #32                                         \n\t"
    499                     "   vld2.8  {q0, q1} , [%[src]]!                                \n\t"
    500                     "   vswp q0, q1                                                 \n\t"
    501                     "   cmp %[n], #32                                               \n\t"
    502                     "   vst2.8  {q0,q1},[%[dst]]!                                   \n\t"
    503                     "   bge 0b                                                      \n\t"
    504                     "1: @ Is there enough data?                                     \n\t"
    505                     "   cmp %[n], #16                                               \n\t"
    506                     "   blt 3f                                                      \n\t"
    507                     "2: @ 16 byte swap                                              \n\t"
    508                     "   sub %[n], %[n], #16                                         \n\t"
    509                     "   vld2.8  {d0, d1} , [%[src]]!                                \n\t"
    510                     "   vswp d0, d1                                                 \n\t"
    511                     "   cmp %[n], #16                                               \n\t"
    512                     "   vst2.8  {d0,d1},[%[dst]]!                                   \n\t"
    513                     "   bge 2b                                                      \n\t"
    514                     "3: @ Is there enough data?                                     \n\t"
    515                     "   cmp %[n], #8                                                \n\t"
    516                     "   blt 5f                                                      \n\t"
    517                     "4: @ 8 byte swap                                               \n\t"
    518                     "   sub %[n], %[n], #8                                          \n\t"
    519                     "   vld2.8  {d0, d1} , [%[src]]!                                \n\t"
    520                     "   vswp d0, d1                                                 \n\t"
    521                     "   cmp %[n], #8                                                \n\t"
    522                     "   vst2.8  {d0[0],d1[0]},[%[dst]]!                             \n\t"
    523                     "   bge 4b                                                      \n\t"
    524                     "5: @ end                                                       \n\t"
    525 #ifdef NEEDS_ARM_ERRATA_754319_754320
    526                     "   vmov s0,s0  @ add noop for errata item                      \n\t"
    527 #endif
    528                     : [dst] "+r" (bufferDst_UV), [src] "+r" (bufferSrc_UV), [n] "+r" (n)
    529                     : [src_stride] "r" (stride_bytes)
    530                     : "cc", "memory", "q0", "q1"
    531                     );
    532                 }
    533             } else if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) {
    534                  uint16_t *bufferDst_U;
    535                  uint16_t *bufferDst_V;
    536 
    537                 // Step 2: UV plane: convert NV12 to YV12 by de-interleaving U & V
    538                 // TODO(XXX): This version of CameraHal assumes NV12 format it set at
    539                 //            camera adapter to support YV12. Need to address for
    540                 //            USBCamera
    541 
    542                 bufferDst_V = (uint16_t *) (((uint8_t*)dst)+row*height);
    543                 bufferDst_U = (uint16_t *) (((uint8_t*)dst)+row*height+row*height/4);
    544 
    545                 for (int i = 0 ; i < height/2 ; i++, bufferSrc_UV += alignedRow/2) {
    546                     int n = width;
    547                     asm volatile (
    548                     "   pld [%[src], %[src_stride], lsl #2]                         \n\t"
    549                     "   cmp %[n], #32                                               \n\t"
    550                     "   blt 1f                                                      \n\t"
    551                     "0: @ 32 byte swap                                              \n\t"
    552                     "   sub %[n], %[n], #32                                         \n\t"
    553                     "   vld2.8  {q0, q1} , [%[src]]!                                \n\t"
    554                     "   cmp %[n], #32                                               \n\t"
    555                     "   vst1.8  {q1},[%[dst_v]]!                                    \n\t"
    556                     "   vst1.8  {q0},[%[dst_u]]!                                    \n\t"
    557                     "   bge 0b                                                      \n\t"
    558                     "1: @ Is there enough data?                                     \n\t"
    559                     "   cmp %[n], #16                                               \n\t"
    560                     "   blt 3f                                                      \n\t"
    561                     "2: @ 16 byte swap                                              \n\t"
    562                     "   sub %[n], %[n], #16                                         \n\t"
    563                     "   vld2.8  {d0, d1} , [%[src]]!                                \n\t"
    564                     "   cmp %[n], #16                                               \n\t"
    565                     "   vst1.8  {d1},[%[dst_v]]!                                    \n\t"
    566                     "   vst1.8  {d0},[%[dst_u]]!                                    \n\t"
    567                     "   bge 2b                                                      \n\t"
    568                     "3: @ Is there enough data?                                     \n\t"
    569                     "   cmp %[n], #8                                                \n\t"
    570                     "   blt 5f                                                      \n\t"
    571                     "4: @ 8 byte swap                                               \n\t"
    572                     "   sub %[n], %[n], #8                                          \n\t"
    573                     "   vld2.8  {d0, d1} , [%[src]]!                                \n\t"
    574                     "   cmp %[n], #8                                                \n\t"
    575                     "   vst1.8  {d1[0]},[%[dst_v]]!                                 \n\t"
    576                     "   vst1.8  {d0[0]},[%[dst_u]]!                                 \n\t"
    577                     "   bge 4b                                                      \n\t"
    578                     "5: @ end                                                       \n\t"
    579 #ifdef NEEDS_ARM_ERRATA_754319_754320
    580                     "   vmov s0,s0  @ add noop for errata item                      \n\t"
    581 #endif
    582                     : [dst_u] "+r" (bufferDst_U), [dst_v] "+r" (bufferDst_V),
    583                       [src] "+r" (bufferSrc_UV), [n] "+r" (n)
    584                     : [src_stride] "r" (stride_bytes)
    585                     : "cc", "memory", "q0", "q1"
    586                     );
    587                 }
    588             }
    589             return ;
    590 
    591         } else if(strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_RGB565) == 0) {
    592             bytesPerPixel = 2;
    593         }
    594     }
    595 
    596     bufferDst = ( unsigned char * ) dst;
    597     bufferSrc = ( unsigned char * ) y_uv[0];
    598     row = width*bytesPerPixel;
    599     alignedRow = ( row + ( stride -1 ) ) & ( ~ ( stride -1 ) );
    600 
    601     //iterate through each row
    602     for ( int i = 0 ; i < height ; i++,  bufferSrc += alignedRow, bufferDst += row) {
    603         memcpy(bufferDst, bufferSrc, row);
    604     }
    605 }
    606 
    607 void AppCallbackNotifier::copyAndSendPictureFrame(CameraFrame* frame, int32_t msgType)
    608 {
    609     camera_memory_t* picture = NULL;
    610     void *dest = NULL, *src = NULL;
    611 
    612     // scope for lock
    613     {
    614         Mutex::Autolock lock(mLock);
    615 
    616         if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED) {
    617             goto exit;
    618         }
    619 
    620         picture = mRequestMemory(-1, frame->mLength, 1, NULL);
    621 
    622         if (NULL != picture) {
    623             dest = picture->data;
    624             if (NULL != dest) {
    625                 src = (void *) ((unsigned int) frame->mBuffer + frame->mOffset);
    626                 memcpy(dest, src, frame->mLength);
    627             }
    628         }
    629     }
    630 
    631  exit:
    632     mFrameProvider->returnFrame(frame->mBuffer, (CameraFrame::FrameType) frame->mFrameType);
    633 
    634     if(picture) {
    635         if((mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) &&
    636            mCameraHal->msgTypeEnabled(msgType)) {
    637             mDataCb(msgType, picture, 0, NULL, mCallbackCookie);
    638         }
    639         picture->release(picture);
    640     }
    641 }
    642 
    643 void AppCallbackNotifier::copyAndSendPreviewFrame(CameraFrame* frame, int32_t msgType)
    644 {
    645     camera_memory_t* picture = NULL;
    646     void* dest = NULL;
    647 
    648     // scope for lock
    649     {
    650         Mutex::Autolock lock(mLock);
    651 
    652         if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED) {
    653             goto exit;
    654         }
    655 
    656         if (!mPreviewMemory || !frame->mBuffer) {
    657             CAMHAL_LOGDA("Error! One of the buffer is NULL");
    658             goto exit;
    659         }
    660 
    661 
    662         dest = (void*) mPreviewBufs[mPreviewBufCount];
    663 
    664         CAMHAL_LOGVB("%d:copy2Dto1D(%p, %p, %d, %d, %d, %d, %d,%s)",
    665                      __LINE__,
    666                       buf,
    667                       frame->mBuffer,
    668                       frame->mWidth,
    669                       frame->mHeight,
    670                       frame->mAlignment,
    671                       2,
    672                       frame->mLength,
    673                       mPreviewPixelFormat);
    674 
    675         if ( NULL != dest ) {
    676             // data sync frames don't need conversion
    677             if (CameraFrame::FRAME_DATA_SYNC == frame->mFrameType) {
    678                 if ( (mPreviewMemory->size / MAX_BUFFERS) >= frame->mLength ) {
    679                     memcpy(dest, (void*) frame->mBuffer, frame->mLength);
    680                 } else {
    681                     memset(dest, 0, (mPreviewMemory->size / MAX_BUFFERS));
    682                 }
    683             } else {
    684               if ((NULL == frame->mYuv[0]) || (NULL == frame->mYuv[1])){
    685                 CAMHAL_LOGEA("Error! One of the YUV Pointer is NULL");
    686                 goto exit;
    687               }
    688               else{
    689                 copy2Dto1D(dest,
    690                            frame->mYuv,
    691                            frame->mWidth,
    692                            frame->mHeight,
    693                            frame->mAlignment,
    694                            frame->mOffset,
    695                            2,
    696                            frame->mLength,
    697                            mPreviewPixelFormat);
    698               }
    699             }
    700         }
    701     }
    702 
    703  exit:
    704     mFrameProvider->returnFrame(frame->mBuffer, (CameraFrame::FrameType) frame->mFrameType);
    705 
    706     if((mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) &&
    707        mCameraHal->msgTypeEnabled(msgType) &&
    708        (dest != NULL)) {
    709         mDataCb(msgType, mPreviewMemory, mPreviewBufCount, NULL, mCallbackCookie);
    710     }
    711 
    712     // increment for next buffer
    713     mPreviewBufCount = (mPreviewBufCount + 1) % AppCallbackNotifier::MAX_BUFFERS;
    714 }
    715 
    716 status_t AppCallbackNotifier::dummyRaw()
    717 {
    718     LOG_FUNCTION_NAME;
    719 
    720     if ( NULL == mRequestMemory ) {
    721         CAMHAL_LOGEA("Can't allocate memory for dummy raw callback!");
    722         return NO_INIT;
    723     }
    724 
    725     if ( ( NULL != mCameraHal ) &&
    726          ( NULL != mDataCb) &&
    727          ( NULL != mNotifyCb ) ){
    728 
    729         if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) ) {
    730             camera_memory_t *dummyRaw = mRequestMemory(-1, 1, 1, NULL);
    731 
    732             if ( NULL == dummyRaw ) {
    733                 CAMHAL_LOGEA("Dummy raw buffer allocation failed!");
    734                 return NO_MEMORY;
    735             }
    736 
    737             mDataCb(CAMERA_MSG_RAW_IMAGE, dummyRaw, 0, NULL, mCallbackCookie);
    738 
    739             dummyRaw->release(dummyRaw);
    740         } else if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY) ) {
    741             mNotifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCallbackCookie);
    742         }
    743     }
    744 
    745     LOG_FUNCTION_NAME_EXIT;
    746 
    747     return NO_ERROR;
    748 }
    749 
    750 void AppCallbackNotifier::notifyFrame()
    751 {
    752     ///Receive and send the frame notifications to app
    753     TIUTILS::Message msg;
    754     CameraFrame *frame;
    755     MemoryHeapBase *heap;
    756     MemoryBase *buffer = NULL;
    757     sp<MemoryBase> memBase;
    758     void *buf = NULL;
    759 
    760     LOG_FUNCTION_NAME;
    761 
    762     {
    763         Mutex::Autolock lock(mLock);
    764         if(!mFrameQ.isEmpty()) {
    765             mFrameQ.get(&msg);
    766         } else {
    767             return;
    768         }
    769     }
    770 
    771     bool ret = true;
    772 
    773     frame = NULL;
    774     switch(msg.command)
    775         {
    776         case AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME:
    777 
    778                 frame = (CameraFrame *) msg.arg1;
    779                 if(!frame)
    780                     {
    781                     break;
    782                     }
    783 
    784                 if ( (CameraFrame::RAW_FRAME == frame->mFrameType )&&
    785                     ( NULL != mCameraHal ) &&
    786                     ( NULL != mDataCb) &&
    787                     ( NULL != mNotifyCb ) )
    788                     {
    789 
    790                     if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) )
    791                         {
    792 #ifdef COPY_IMAGE_BUFFER
    793                         copyAndSendPictureFrame(frame, CAMERA_MSG_RAW_IMAGE);
    794 #else
    795                         //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase
    796 #endif
    797                         }
    798                     else {
    799                         if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY) ) {
    800                             mNotifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCallbackCookie);
    801                         }
    802                         mFrameProvider->returnFrame(frame->mBuffer,
    803                                                     (CameraFrame::FrameType) frame->mFrameType);
    804                     }
    805 
    806                     mRawAvailable = true;
    807 
    808                     }
    809                 else if ( (CameraFrame::IMAGE_FRAME == frame->mFrameType) &&
    810                           (NULL != mCameraHal) &&
    811                           (NULL != mDataCb) &&
    812                           (CameraFrame::ENCODE_RAW_YUV422I_TO_JPEG & frame->mQuirks) )
    813                     {
    814 
    815                     int encode_quality = 100, tn_quality = 100;
    816                     int tn_width, tn_height;
    817                     unsigned int current_snapshot = 0;
    818                     Encoder_libjpeg::params *main_jpeg = NULL, *tn_jpeg = NULL;
    819                     void* exif_data = NULL;
    820                     camera_memory_t* raw_picture = mRequestMemory(-1, frame->mLength, 1, NULL);
    821 
    822                     if(raw_picture) {
    823                         buf = raw_picture->data;
    824                     }
    825 
    826                     CameraParameters parameters;
    827                     char *params = mCameraHal->getParameters();
    828                     const String8 strParams(params);
    829                     parameters.unflatten(strParams);
    830 
    831                     encode_quality = parameters.getInt(CameraParameters::KEY_JPEG_QUALITY);
    832                     if (encode_quality < 0 || encode_quality > 100) {
    833                         encode_quality = 100;
    834                     }
    835 
    836                     tn_quality = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
    837                     if (tn_quality < 0 || tn_quality > 100) {
    838                         tn_quality = 100;
    839                     }
    840 
    841                     if (CameraFrame::HAS_EXIF_DATA & frame->mQuirks) {
    842                         exif_data = frame->mCookie2;
    843                     }
    844 
    845                     main_jpeg = (Encoder_libjpeg::params*)
    846                                     malloc(sizeof(Encoder_libjpeg::params));
    847 
    848                     // Video snapshot with LDCNSF on adds a few bytes start offset
    849                     // and a few bytes on every line. They must be skipped.
    850                     int rightCrop = frame->mAlignment/2 - frame->mWidth;
    851 
    852                     CAMHAL_LOGDB("Video snapshot right crop = %d", rightCrop);
    853                     CAMHAL_LOGDB("Video snapshot offset = %d", frame->mOffset);
    854 
    855                     if (main_jpeg) {
    856                         main_jpeg->src = (uint8_t*) frame->mBuffer;
    857                         main_jpeg->src_size = frame->mLength;
    858                         main_jpeg->dst = (uint8_t*) buf;
    859                         main_jpeg->dst_size = frame->mLength;
    860                         main_jpeg->quality = encode_quality;
    861                         main_jpeg->in_width = frame->mAlignment/2; // use stride here
    862                         main_jpeg->in_height = frame->mHeight;
    863                         main_jpeg->out_width = frame->mAlignment/2;
    864                         main_jpeg->out_height = frame->mHeight;
    865                         main_jpeg->right_crop = rightCrop;
    866                         main_jpeg->start_offset = frame->mOffset;
    867                         main_jpeg->format = CameraParameters::PIXEL_FORMAT_YUV422I;
    868                     }
    869 
    870                     tn_width = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
    871                     tn_height = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
    872 
    873                     if ((tn_width > 0) && (tn_height > 0)) {
    874                         tn_jpeg = (Encoder_libjpeg::params*)
    875                                       malloc(sizeof(Encoder_libjpeg::params));
    876                         // if malloc fails just keep going and encode main jpeg
    877                         if (!tn_jpeg) {
    878                             tn_jpeg = NULL;
    879                         }
    880                     }
    881 
    882                     if (tn_jpeg) {
    883                         int width, height;
    884                         parameters.getPreviewSize(&width,&height);
    885                         current_snapshot = (mPreviewBufCount + MAX_BUFFERS - 1) % MAX_BUFFERS;
    886                         tn_jpeg->src = (uint8_t*) mPreviewBufs[current_snapshot];
    887                         tn_jpeg->src_size = mPreviewMemory->size / MAX_BUFFERS;
    888                         tn_jpeg->dst = (uint8_t*) malloc(tn_jpeg->src_size);
    889                         tn_jpeg->dst_size = tn_jpeg->src_size;
    890                         tn_jpeg->quality = tn_quality;
    891                         tn_jpeg->in_width = width;
    892                         tn_jpeg->in_height = height;
    893                         tn_jpeg->out_width = tn_width;
    894                         tn_jpeg->out_height = tn_height;
    895                         tn_jpeg->right_crop = 0;
    896                         tn_jpeg->start_offset = 0;
    897                         tn_jpeg->format = CameraParameters::PIXEL_FORMAT_YUV420SP;;
    898                     }
    899 
    900                     sp<Encoder_libjpeg> encoder = new Encoder_libjpeg(main_jpeg,
    901                                                       tn_jpeg,
    902                                                       AppCallbackNotifierEncoderCallback,
    903                                                       (CameraFrame::FrameType)frame->mFrameType,
    904                                                       this,
    905                                                       raw_picture,
    906                                                       exif_data);
    907                     encoder->run();
    908                     gEncoderQueue.add(frame->mBuffer, encoder);
    909                     encoder.clear();
    910                     if (params != NULL)
    911                       {
    912                         mCameraHal->putParameters(params);
    913                       }
    914                     }
    915                 else if ( ( CameraFrame::IMAGE_FRAME == frame->mFrameType ) &&
    916                              ( NULL != mCameraHal ) &&
    917                              ( NULL != mDataCb) )
    918                     {
    919 
    920                     // CTS, MTS requirements: Every 'takePicture()' call
    921                     // who registers a raw callback should receive one
    922                     // as well. This is  not always the case with
    923                     // CameraAdapters though.
    924                     if (!mRawAvailable) {
    925                         dummyRaw();
    926                     } else {
    927                         mRawAvailable = false;
    928                     }
    929 
    930 #ifdef COPY_IMAGE_BUFFER
    931                     {
    932                         Mutex::Autolock lock(mBurstLock);
    933 #if 0 //TODO: enable burst mode later
    934                         if ( mBurst )
    935                         {
    936                             `(CAMERA_MSG_BURST_IMAGE, JPEGPictureMemBase, mCallbackCookie);
    937                         }
    938                         else
    939 #endif
    940                         {
    941                             copyAndSendPictureFrame(frame, CAMERA_MSG_COMPRESSED_IMAGE);
    942                         }
    943                     }
    944 #else
    945                      //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase
    946 #endif
    947                     }
    948                 else if ( ( CameraFrame::VIDEO_FRAME_SYNC == frame->mFrameType ) &&
    949                              ( NULL != mCameraHal ) &&
    950                              ( NULL != mDataCb) &&
    951                              ( mCameraHal->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME)  ) )
    952                     {
    953                     mRecordingLock.lock();
    954                     if(mRecording)
    955                         {
    956                         if(mUseMetaDataBufferMode)
    957                             {
    958                             camera_memory_t *videoMedatadaBufferMemory =
    959                                              (camera_memory_t *) mVideoMetadataBufferMemoryMap.valueFor((uint32_t) frame->mBuffer);
    960                             video_metadata_t *videoMetadataBuffer = (video_metadata_t *) videoMedatadaBufferMemory->data;
    961 
    962                             if( (NULL == videoMedatadaBufferMemory) || (NULL == videoMetadataBuffer) || (NULL == frame->mBuffer) )
    963                                 {
    964                                 CAMHAL_LOGEA("Error! One of the video buffers is NULL");
    965                                 break;
    966                                 }
    967 
    968                             if ( mUseVideoBuffers )
    969                               {
    970                                 int vBuf = mVideoMap.valueFor((uint32_t) frame->mBuffer);
    971                                 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
    972                                 Rect bounds;
    973                                 bounds.left = 0;
    974                                 bounds.top = 0;
    975                                 bounds.right = mVideoWidth;
    976                                 bounds.bottom = mVideoHeight;
    977 
    978                                 void *y_uv[2];
    979                                 mapper.lock((buffer_handle_t)vBuf, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
    980 
    981                                 structConvImage input =  {frame->mWidth,
    982                                                           frame->mHeight,
    983                                                           4096,
    984                                                           IC_FORMAT_YCbCr420_lp,
    985                                                           (mmByte *)frame->mYuv[0],
    986                                                           (mmByte *)frame->mYuv[1],
    987                                                           frame->mOffset};
    988 
    989                                 structConvImage output = {mVideoWidth,
    990                                                           mVideoHeight,
    991                                                           4096,
    992                                                           IC_FORMAT_YCbCr420_lp,
    993                                                           (mmByte *)y_uv[0],
    994                                                           (mmByte *)y_uv[1],
    995                                                           0};
    996 
    997                                 VT_resizeFrame_Video_opt2_lp(&input, &output, NULL, 0);
    998                                 mapper.unlock((buffer_handle_t)vBuf);
    999                                 videoMetadataBuffer->metadataBufferType = (int) kMetadataBufferTypeCameraSource;
   1000                                 videoMetadataBuffer->handle = (void *)vBuf;
   1001                                 videoMetadataBuffer->offset = 0;
   1002                               }
   1003                             else
   1004                               {
   1005                                 videoMetadataBuffer->metadataBufferType = (int) kMetadataBufferTypeCameraSource;
   1006                                 videoMetadataBuffer->handle = frame->mBuffer;
   1007                                 videoMetadataBuffer->offset = frame->mOffset;
   1008                               }
   1009 
   1010                             CAMHAL_LOGVB("mDataCbTimestamp : frame->mBuffer=0x%x, videoMetadataBuffer=0x%x, videoMedatadaBufferMemory=0x%x",
   1011                                             frame->mBuffer, videoMetadataBuffer, videoMedatadaBufferMemory);
   1012 
   1013                             mDataCbTimestamp(frame->mTimestamp, CAMERA_MSG_VIDEO_FRAME,
   1014                                                 videoMedatadaBufferMemory, 0, mCallbackCookie);
   1015                             }
   1016                         else
   1017                             {
   1018                             //TODO: Need to revisit this, should ideally be mapping the TILER buffer using mRequestMemory
   1019                             camera_memory_t* fakebuf = mRequestMemory(-1, 4, 1, NULL);
   1020                             if( (NULL == fakebuf) || ( NULL == fakebuf->data) || ( NULL == frame->mBuffer))
   1021                                 {
   1022                                 CAMHAL_LOGEA("Error! One of the video buffers is NULL");
   1023                                 break;
   1024                                 }
   1025 
   1026                             fakebuf->data = frame->mBuffer;
   1027                             mDataCbTimestamp(frame->mTimestamp, CAMERA_MSG_VIDEO_FRAME, fakebuf, 0, mCallbackCookie);
   1028                             fakebuf->release(fakebuf);
   1029                             }
   1030                         }
   1031                     mRecordingLock.unlock();
   1032 
   1033                     }
   1034                 else if(( CameraFrame::SNAPSHOT_FRAME == frame->mFrameType ) &&
   1035                              ( NULL != mCameraHal ) &&
   1036                              ( NULL != mDataCb) &&
   1037                              ( NULL != mNotifyCb)) {
   1038                     //When enabled, measurement data is sent instead of video data
   1039                     if ( !mMeasurementEnabled ) {
   1040                         copyAndSendPreviewFrame(frame, CAMERA_MSG_POSTVIEW_FRAME);
   1041                     } else {
   1042                         mFrameProvider->returnFrame(frame->mBuffer,
   1043                                                     (CameraFrame::FrameType) frame->mFrameType);
   1044                     }
   1045                 }
   1046                 else if ( ( CameraFrame::PREVIEW_FRAME_SYNC== frame->mFrameType ) &&
   1047                             ( NULL != mCameraHal ) &&
   1048                             ( NULL != mDataCb) &&
   1049                             ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) ) {
   1050                     //When enabled, measurement data is sent instead of video data
   1051                     if ( !mMeasurementEnabled ) {
   1052                         copyAndSendPreviewFrame(frame, CAMERA_MSG_PREVIEW_FRAME);
   1053                     } else {
   1054                          mFrameProvider->returnFrame(frame->mBuffer,
   1055                                                      (CameraFrame::FrameType) frame->mFrameType);
   1056                     }
   1057                 }
   1058                 else if ( ( CameraFrame::FRAME_DATA_SYNC == frame->mFrameType ) &&
   1059                             ( NULL != mCameraHal ) &&
   1060                             ( NULL != mDataCb) &&
   1061                             ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) ) {
   1062                     copyAndSendPreviewFrame(frame, CAMERA_MSG_PREVIEW_FRAME);
   1063                 } else {
   1064                     mFrameProvider->returnFrame(frame->mBuffer,
   1065                                                 ( CameraFrame::FrameType ) frame->mFrameType);
   1066                     CAMHAL_LOGDB("Frame type 0x%x is still unsupported!", frame->mFrameType);
   1067                 }
   1068 
   1069                 break;
   1070 
   1071         default:
   1072 
   1073             break;
   1074 
   1075         };
   1076 
   1077 exit:
   1078 
   1079     if ( NULL != frame )
   1080         {
   1081         delete frame;
   1082         }
   1083 
   1084     LOG_FUNCTION_NAME_EXIT;
   1085 }
   1086 
   1087 void AppCallbackNotifier::frameCallbackRelay(CameraFrame* caFrame)
   1088 {
   1089     LOG_FUNCTION_NAME;
   1090     AppCallbackNotifier *appcbn = (AppCallbackNotifier*) (caFrame->mCookie);
   1091     appcbn->frameCallback(caFrame);
   1092     LOG_FUNCTION_NAME_EXIT;
   1093 }
   1094 
   1095 void AppCallbackNotifier::frameCallback(CameraFrame* caFrame)
   1096 {
   1097     ///Post the event to the event queue of AppCallbackNotifier
   1098     TIUTILS::Message msg;
   1099     CameraFrame *frame;
   1100 
   1101     LOG_FUNCTION_NAME;
   1102 
   1103     if ( NULL != caFrame )
   1104         {
   1105 
   1106         frame = new CameraFrame(*caFrame);
   1107         if ( NULL != frame )
   1108             {
   1109               msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME;
   1110               msg.arg1 = frame;
   1111               mFrameQ.put(&msg);
   1112             }
   1113         else
   1114             {
   1115             CAMHAL_LOGEA("Not enough resources to allocate CameraFrame");
   1116             }
   1117 
   1118         }
   1119 
   1120     LOG_FUNCTION_NAME_EXIT;
   1121 }
   1122 
   1123 void AppCallbackNotifier::flushAndReturnFrames()
   1124 {
   1125     TIUTILS::Message msg;
   1126     CameraFrame *frame;
   1127 
   1128     Mutex::Autolock lock(mLock);
   1129     while (!mFrameQ.isEmpty()) {
   1130         mFrameQ.get(&msg);
   1131         frame = (CameraFrame*) msg.arg1;
   1132         if (frame) {
   1133             mFrameProvider->returnFrame(frame->mBuffer,
   1134                                         (CameraFrame::FrameType) frame->mFrameType);
   1135         }
   1136     }
   1137 
   1138     LOG_FUNCTION_NAME_EXIT;
   1139 }
   1140 
   1141 void AppCallbackNotifier::eventCallbackRelay(CameraHalEvent* chEvt)
   1142 {
   1143     LOG_FUNCTION_NAME;
   1144     AppCallbackNotifier *appcbn = (AppCallbackNotifier*) (chEvt->mCookie);
   1145     appcbn->eventCallback(chEvt);
   1146     LOG_FUNCTION_NAME_EXIT;
   1147 }
   1148 
   1149 void AppCallbackNotifier::eventCallback(CameraHalEvent* chEvt)
   1150 {
   1151 
   1152     ///Post the event to the event queue of AppCallbackNotifier
   1153     TIUTILS::Message msg;
   1154     CameraHalEvent *event;
   1155 
   1156 
   1157     LOG_FUNCTION_NAME;
   1158 
   1159     if ( NULL != chEvt )
   1160         {
   1161 
   1162         event = new CameraHalEvent(*chEvt);
   1163         if ( NULL != event )
   1164             {
   1165             msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_EVENT;
   1166             msg.arg1 = event;
   1167             {
   1168             Mutex::Autolock lock(mLock);
   1169             mEventQ.put(&msg);
   1170             }
   1171             }
   1172         else
   1173             {
   1174             CAMHAL_LOGEA("Not enough resources to allocate CameraHalEvent");
   1175             }
   1176 
   1177         }
   1178 
   1179     LOG_FUNCTION_NAME_EXIT;
   1180 }
   1181 
   1182 
   1183 void AppCallbackNotifier::flushEventQueue()
   1184 {
   1185 
   1186     {
   1187     Mutex::Autolock lock(mLock);
   1188     mEventQ.clear();
   1189     }
   1190 }
   1191 
   1192 
   1193 bool AppCallbackNotifier::processMessage()
   1194 {
   1195     ///Retrieve the command from the command queue and process it
   1196     TIUTILS::Message msg;
   1197 
   1198     LOG_FUNCTION_NAME;
   1199 
   1200     CAMHAL_LOGDA("+Msg get...");
   1201     mNotificationThread->msgQ().get(&msg);
   1202     CAMHAL_LOGDA("-Msg get...");
   1203     bool ret = true;
   1204 
   1205     switch(msg.command)
   1206       {
   1207         case NotificationThread::NOTIFIER_EXIT:
   1208           {
   1209             CAMHAL_LOGI("Received NOTIFIER_EXIT command from Camera HAL");
   1210             mNotifierState = AppCallbackNotifier::NOTIFIER_EXITED;
   1211             ret = false;
   1212             break;
   1213           }
   1214         default:
   1215           {
   1216             CAMHAL_LOGEA("Error: ProcessMsg() command from Camera HAL");
   1217             break;
   1218           }
   1219       }
   1220 
   1221     LOG_FUNCTION_NAME_EXIT;
   1222 
   1223     return ret;
   1224 
   1225 
   1226 }
   1227 
   1228 AppCallbackNotifier::~AppCallbackNotifier()
   1229 {
   1230     LOG_FUNCTION_NAME;
   1231 
   1232     ///Stop app callback notifier if not already stopped
   1233     stop();
   1234 
   1235     ///Unregister with the frame provider
   1236     if ( NULL != mFrameProvider )
   1237         {
   1238         mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES);
   1239         }
   1240 
   1241     //unregister with the event provider
   1242     if ( NULL != mEventProvider )
   1243         {
   1244         mEventProvider->disableEventNotification(CameraHalEvent::ALL_EVENTS);
   1245         }
   1246 
   1247     TIUTILS::Message msg = {0,0,0,0,0,0};
   1248     msg.command = NotificationThread::NOTIFIER_EXIT;
   1249 
   1250     ///Post the message to display thread
   1251     mNotificationThread->msgQ().put(&msg);
   1252 
   1253     //Exit and cleanup the thread
   1254     mNotificationThread->requestExit();
   1255     mNotificationThread->join();
   1256 
   1257     //Delete the display thread
   1258     mNotificationThread.clear();
   1259 
   1260 
   1261     ///Free the event and frame providers
   1262     if ( NULL != mEventProvider )
   1263         {
   1264         ///Deleting the event provider
   1265         CAMHAL_LOGDA("Stopping Event Provider");
   1266         delete mEventProvider;
   1267         mEventProvider = NULL;
   1268         }
   1269 
   1270     if ( NULL != mFrameProvider )
   1271         {
   1272         ///Deleting the frame provider
   1273         CAMHAL_LOGDA("Stopping Frame Provider");
   1274         delete mFrameProvider;
   1275         mFrameProvider = NULL;
   1276         }
   1277 
   1278     releaseSharedVideoBuffers();
   1279 
   1280     LOG_FUNCTION_NAME_EXIT;
   1281 }
   1282 
   1283 //Free all video heaps and buffers
   1284 void AppCallbackNotifier::releaseSharedVideoBuffers()
   1285 {
   1286     LOG_FUNCTION_NAME;
   1287 
   1288     if(mUseMetaDataBufferMode)
   1289     {
   1290         camera_memory_t* videoMedatadaBufferMemory;
   1291         for (unsigned int i = 0; i < mVideoMetadataBufferMemoryMap.size();  i++)
   1292             {
   1293             videoMedatadaBufferMemory = (camera_memory_t*) mVideoMetadataBufferMemoryMap.valueAt(i);
   1294             if(NULL != videoMedatadaBufferMemory)
   1295                 {
   1296                 videoMedatadaBufferMemory->release(videoMedatadaBufferMemory);
   1297                 CAMHAL_LOGDB("Released  videoMedatadaBufferMemory=0x%x", videoMedatadaBufferMemory);
   1298                 }
   1299             }
   1300 
   1301         mVideoMetadataBufferMemoryMap.clear();
   1302         mVideoMetadataBufferReverseMap.clear();
   1303         if (mUseVideoBuffers)
   1304             {
   1305             mVideoMap.clear();
   1306             }
   1307     }
   1308 
   1309     LOG_FUNCTION_NAME_EXIT;
   1310 }
   1311 
   1312 void AppCallbackNotifier::setEventProvider(int32_t eventMask, MessageNotifier * eventNotifier)
   1313 {
   1314 
   1315     LOG_FUNCTION_NAME;
   1316     ///@remarks There is no NULL check here. We will check
   1317     ///for NULL when we get start command from CameraHal
   1318     ///@Remarks Currently only one event provider (CameraAdapter) is supported
   1319     ///@todo Have an array of event providers for each event bitmask
   1320     mEventProvider = new EventProvider(eventNotifier, this, eventCallbackRelay);
   1321     if ( NULL == mEventProvider )
   1322         {
   1323         CAMHAL_LOGEA("Error in creating EventProvider");
   1324         }
   1325     else
   1326         {
   1327         mEventProvider->enableEventNotification(eventMask);
   1328         }
   1329 
   1330     LOG_FUNCTION_NAME_EXIT;
   1331 }
   1332 
   1333 void AppCallbackNotifier::setFrameProvider(FrameNotifier *frameNotifier)
   1334 {
   1335     LOG_FUNCTION_NAME;
   1336     ///@remarks There is no NULL check here. We will check
   1337     ///for NULL when we get the start command from CameraAdapter
   1338     mFrameProvider = new FrameProvider(frameNotifier, this, frameCallbackRelay);
   1339     if ( NULL == mFrameProvider )
   1340         {
   1341         CAMHAL_LOGEA("Error in creating FrameProvider");
   1342         }
   1343     else
   1344         {
   1345         //Register only for captured images and RAW for now
   1346         //TODO: Register for and handle all types of frames
   1347         mFrameProvider->enableFrameNotification(CameraFrame::IMAGE_FRAME);
   1348         mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME);
   1349         }
   1350 
   1351     LOG_FUNCTION_NAME_EXIT;
   1352 }
   1353 
   1354 status_t AppCallbackNotifier::startPreviewCallbacks(CameraParameters &params, void *buffers, uint32_t *offsets, int fd, size_t length, size_t count)
   1355 {
   1356     sp<MemoryHeapBase> heap;
   1357     sp<MemoryBase> buffer;
   1358     unsigned int *bufArr;
   1359     size_t size = 0;
   1360 
   1361     LOG_FUNCTION_NAME;
   1362 
   1363     Mutex::Autolock lock(mLock);
   1364 
   1365     if ( NULL == mFrameProvider )
   1366         {
   1367         CAMHAL_LOGEA("Trying to start video recording without FrameProvider");
   1368         return -EINVAL;
   1369         }
   1370 
   1371     if ( mPreviewing )
   1372         {
   1373         CAMHAL_LOGDA("+Already previewing");
   1374         return NO_INIT;
   1375         }
   1376 
   1377     int w,h;
   1378     ///Get preview size
   1379     params.getPreviewSize(&w, &h);
   1380 
   1381     //Get the preview pixel format
   1382     mPreviewPixelFormat = params.getPreviewFormat();
   1383 
   1384      if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
   1385         {
   1386         size = w*h*2;
   1387         mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_YUV422I;
   1388         }
   1389     else if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ||
   1390             strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420P) == 0)
   1391         {
   1392         size = (w*h*3)/2;
   1393         mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_YUV420SP;
   1394         }
   1395     else if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0)
   1396         {
   1397         size = w*h*2;
   1398         mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_RGB565;
   1399         }
   1400 
   1401     mPreviewMemory = mRequestMemory(-1, size, AppCallbackNotifier::MAX_BUFFERS, NULL);
   1402     if (!mPreviewMemory) {
   1403         return NO_MEMORY;
   1404     }
   1405 
   1406     for (int i=0; i < AppCallbackNotifier::MAX_BUFFERS; i++) {
   1407         mPreviewBufs[i] = (unsigned char*) mPreviewMemory->data + (i*size);
   1408     }
   1409 
   1410     if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME ) ) {
   1411          mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
   1412     }
   1413 
   1414     mPreviewBufCount = 0;
   1415 
   1416     mPreviewing = true;
   1417 
   1418     LOG_FUNCTION_NAME;
   1419 
   1420     return NO_ERROR;
   1421 }
   1422 
   1423 void AppCallbackNotifier::setBurst(bool burst)
   1424 {
   1425     LOG_FUNCTION_NAME;
   1426 
   1427     Mutex::Autolock lock(mBurstLock);
   1428 
   1429     mBurst = burst;
   1430 
   1431     LOG_FUNCTION_NAME_EXIT;
   1432 }
   1433 
   1434 void AppCallbackNotifier::useVideoBuffers(bool useVideoBuffers)
   1435 {
   1436   LOG_FUNCTION_NAME;
   1437 
   1438   mUseVideoBuffers = useVideoBuffers;
   1439 
   1440   LOG_FUNCTION_NAME_EXIT;
   1441 }
   1442 
   1443 bool AppCallbackNotifier::getUesVideoBuffers()
   1444 {
   1445     return mUseVideoBuffers;
   1446 }
   1447 
   1448 void AppCallbackNotifier::setVideoRes(int width, int height)
   1449 {
   1450   LOG_FUNCTION_NAME;
   1451 
   1452   mVideoWidth = width;
   1453   mVideoHeight = height;
   1454 
   1455   LOG_FUNCTION_NAME_EXIT;
   1456 }
   1457 
   1458 status_t AppCallbackNotifier::stopPreviewCallbacks()
   1459 {
   1460     sp<MemoryHeapBase> heap;
   1461     sp<MemoryBase> buffer;
   1462 
   1463     LOG_FUNCTION_NAME;
   1464 
   1465     if ( NULL == mFrameProvider )
   1466         {
   1467         CAMHAL_LOGEA("Trying to stop preview callbacks without FrameProvider");
   1468         return -EINVAL;
   1469         }
   1470 
   1471     if ( !mPreviewing )
   1472         {
   1473         return NO_INIT;
   1474         }
   1475 
   1476     mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
   1477 
   1478     {
   1479     Mutex::Autolock lock(mLock);
   1480     mPreviewMemory->release(mPreviewMemory);
   1481     }
   1482 
   1483     mPreviewing = false;
   1484 
   1485     LOG_FUNCTION_NAME_EXIT;
   1486 
   1487     return NO_ERROR;
   1488 
   1489 }
   1490 
   1491 status_t AppCallbackNotifier::useMetaDataBufferMode(bool enable)
   1492 {
   1493     mUseMetaDataBufferMode = enable;
   1494 
   1495     return NO_ERROR;
   1496 }
   1497 
   1498 
   1499 status_t AppCallbackNotifier::startRecording()
   1500 {
   1501     status_t ret = NO_ERROR;
   1502 
   1503     LOG_FUNCTION_NAME;
   1504 
   1505    Mutex::Autolock lock(mRecordingLock);
   1506 
   1507     if ( NULL == mFrameProvider )
   1508         {
   1509         CAMHAL_LOGEA("Trying to start video recording without FrameProvider");
   1510         ret = -1;
   1511         }
   1512 
   1513     if(mRecording)
   1514         {
   1515         return NO_INIT;
   1516         }
   1517 
   1518     if ( NO_ERROR == ret )
   1519         {
   1520          mFrameProvider->enableFrameNotification(CameraFrame::VIDEO_FRAME_SYNC);
   1521         }
   1522 
   1523     mRecording = true;
   1524 
   1525     LOG_FUNCTION_NAME_EXIT;
   1526 
   1527     return ret;
   1528 }
   1529 
   1530 //Allocate metadata buffers for video recording
   1531 status_t AppCallbackNotifier::initSharedVideoBuffers(void *buffers, uint32_t *offsets, int fd, size_t length, size_t count, void *vidBufs)
   1532 {
   1533     status_t ret = NO_ERROR;
   1534     LOG_FUNCTION_NAME;
   1535 
   1536     if(mUseMetaDataBufferMode)
   1537         {
   1538         uint32_t *bufArr = NULL;
   1539         camera_memory_t* videoMedatadaBufferMemory = NULL;
   1540 
   1541         if(NULL == buffers)
   1542             {
   1543             CAMHAL_LOGEA("Error! Video buffers are NULL");
   1544             return BAD_VALUE;
   1545             }
   1546         bufArr = (uint32_t *) buffers;
   1547 
   1548         for (uint32_t i = 0; i < count; i++)
   1549             {
   1550             videoMedatadaBufferMemory = mRequestMemory(-1, sizeof(video_metadata_t), 1, NULL);
   1551             if((NULL == videoMedatadaBufferMemory) || (NULL == videoMedatadaBufferMemory->data))
   1552                 {
   1553                 CAMHAL_LOGEA("Error! Could not allocate memory for Video Metadata Buffers");
   1554                 return NO_MEMORY;
   1555                 }
   1556 
   1557             mVideoMetadataBufferMemoryMap.add(bufArr[i], (uint32_t)(videoMedatadaBufferMemory));
   1558             mVideoMetadataBufferReverseMap.add((uint32_t)(videoMedatadaBufferMemory->data), bufArr[i]);
   1559             CAMHAL_LOGDB("bufArr[%d]=0x%x, videoMedatadaBufferMemory=0x%x, videoMedatadaBufferMemory->data=0x%x",
   1560                     i, bufArr[i], videoMedatadaBufferMemory, videoMedatadaBufferMemory->data);
   1561 
   1562             if (vidBufs != NULL)
   1563               {
   1564                 uint32_t *vBufArr = (uint32_t *) vidBufs;
   1565                 mVideoMap.add(bufArr[i], vBufArr[i]);
   1566                 CAMHAL_LOGVB("bufArr[%d]=0x%x, vBuffArr[%d]=0x%x", i, bufArr[i], i, vBufArr[i]);
   1567               }
   1568             }
   1569         }
   1570 
   1571 exit:
   1572     LOG_FUNCTION_NAME_EXIT;
   1573 
   1574     return ret;
   1575 }
   1576 
   1577 status_t AppCallbackNotifier::stopRecording()
   1578 {
   1579     status_t ret = NO_ERROR;
   1580 
   1581     LOG_FUNCTION_NAME;
   1582 
   1583     Mutex::Autolock lock(mRecordingLock);
   1584 
   1585     if ( NULL == mFrameProvider )
   1586         {
   1587         CAMHAL_LOGEA("Trying to stop video recording without FrameProvider");
   1588         ret = -1;
   1589         }
   1590 
   1591     if(!mRecording)
   1592         {
   1593         return NO_INIT;
   1594         }
   1595 
   1596     if ( NO_ERROR == ret )
   1597         {
   1598          mFrameProvider->disableFrameNotification(CameraFrame::VIDEO_FRAME_SYNC);
   1599         }
   1600 
   1601     ///Release the shared video buffers
   1602     releaseSharedVideoBuffers();
   1603 
   1604     mRecording = false;
   1605 
   1606     LOG_FUNCTION_NAME_EXIT;
   1607 
   1608     return ret;
   1609 }
   1610 
   1611 status_t AppCallbackNotifier::releaseRecordingFrame(const void* mem)
   1612 {
   1613     status_t ret = NO_ERROR;
   1614     void *frame = NULL;
   1615 
   1616     LOG_FUNCTION_NAME;
   1617     if ( NULL == mFrameProvider )
   1618         {
   1619         CAMHAL_LOGEA("Trying to stop video recording without FrameProvider");
   1620         ret = -1;
   1621         }
   1622 
   1623     if ( NULL == mem )
   1624         {
   1625         CAMHAL_LOGEA("Video Frame released is invalid");
   1626         ret = -1;
   1627         }
   1628 
   1629     if( NO_ERROR != ret )
   1630         {
   1631         return ret;
   1632         }
   1633 
   1634     if(mUseMetaDataBufferMode)
   1635         {
   1636         video_metadata_t *videoMetadataBuffer = (video_metadata_t *) mem ;
   1637         frame = (void*) mVideoMetadataBufferReverseMap.valueFor((uint32_t) videoMetadataBuffer);
   1638         CAMHAL_LOGVB("Releasing frame with videoMetadataBuffer=0x%x, videoMetadataBuffer->handle=0x%x & frame handle=0x%x\n",
   1639                        videoMetadataBuffer, videoMetadataBuffer->handle, frame);
   1640         }
   1641     else
   1642         {
   1643         frame = (void*)(*((uint32_t *)mem));
   1644         }
   1645 
   1646     if ( NO_ERROR == ret )
   1647         {
   1648          ret = mFrameProvider->returnFrame(frame, CameraFrame::VIDEO_FRAME_SYNC);
   1649         }
   1650 
   1651     LOG_FUNCTION_NAME_EXIT;
   1652 
   1653     return ret;
   1654 }
   1655 
   1656 status_t AppCallbackNotifier::enableMsgType(int32_t msgType)
   1657 {
   1658     if( msgType & (CAMERA_MSG_POSTVIEW_FRAME | CAMERA_MSG_PREVIEW_FRAME) ) {
   1659         mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
   1660     }
   1661 
   1662     return NO_ERROR;
   1663 }
   1664 
   1665 status_t AppCallbackNotifier::disableMsgType(int32_t msgType)
   1666 {
   1667     if(!mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME | CAMERA_MSG_POSTVIEW_FRAME)) {
   1668         mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
   1669     }
   1670 
   1671     return NO_ERROR;
   1672 
   1673 }
   1674 
   1675 status_t AppCallbackNotifier::start()
   1676 {
   1677     LOG_FUNCTION_NAME;
   1678     if(mNotifierState==AppCallbackNotifier::NOTIFIER_STARTED)
   1679         {
   1680         CAMHAL_LOGDA("AppCallbackNotifier already running");
   1681         LOG_FUNCTION_NAME_EXIT;
   1682         return ALREADY_EXISTS;
   1683         }
   1684 
   1685     ///Check whether initial conditions are met for us to start
   1686     ///A frame provider should be available, if not return error
   1687     if(!mFrameProvider)
   1688         {
   1689         ///AppCallbackNotifier not properly initialized
   1690         CAMHAL_LOGEA("AppCallbackNotifier not properly initialized - Frame provider is NULL");
   1691         LOG_FUNCTION_NAME_EXIT;
   1692         return NO_INIT;
   1693         }
   1694 
   1695     ///At least one event notifier should be available, if not return error
   1696     ///@todo Modify here when there is an array of event providers
   1697     if(!mEventProvider)
   1698         {
   1699         CAMHAL_LOGEA("AppCallbackNotifier not properly initialized - Event provider is NULL");
   1700         LOG_FUNCTION_NAME_EXIT;
   1701         ///AppCallbackNotifier not properly initialized
   1702         return NO_INIT;
   1703         }
   1704 
   1705     mNotifierState = AppCallbackNotifier::NOTIFIER_STARTED;
   1706     CAMHAL_LOGDA(" --> AppCallbackNotifier NOTIFIER_STARTED \n");
   1707 
   1708     gEncoderQueue.clear();
   1709 
   1710     LOG_FUNCTION_NAME_EXIT;
   1711 
   1712     return NO_ERROR;
   1713 
   1714 }
   1715 
   1716 status_t AppCallbackNotifier::stop()
   1717 {
   1718     LOG_FUNCTION_NAME;
   1719 
   1720     if(mNotifierState!=AppCallbackNotifier::NOTIFIER_STARTED)
   1721         {
   1722         CAMHAL_LOGDA("AppCallbackNotifier already in stopped state");
   1723         LOG_FUNCTION_NAME_EXIT;
   1724         return ALREADY_EXISTS;
   1725         }
   1726     {
   1727     Mutex::Autolock lock(mLock);
   1728 
   1729     mNotifierState = AppCallbackNotifier::NOTIFIER_STOPPED;
   1730     CAMHAL_LOGDA(" --> AppCallbackNotifier NOTIFIER_STOPPED \n");
   1731     }
   1732 
   1733     while(!gEncoderQueue.isEmpty()) {
   1734         sp<Encoder_libjpeg> encoder = gEncoderQueue.valueAt(0);
   1735         if(encoder.get()) {
   1736             encoder->cancel();
   1737             encoder->join();
   1738             encoder.clear();
   1739         }
   1740         gEncoderQueue.removeItemsAt(0);
   1741     }
   1742 
   1743     LOG_FUNCTION_NAME_EXIT;
   1744     return NO_ERROR;
   1745 }
   1746 
   1747 
   1748 /*--------------------NotificationHandler Class ENDS here-----------------------------*/
   1749 
   1750 
   1751 
   1752 };
   1753