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