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