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
26namespace Ti {
27namespace Camera {
28
29const int AppCallbackNotifier::NOTIFIER_TIMEOUT = -1;
30android::KeyedVector<void*, android::sp<Encoder_libjpeg> > gEncoderQueue;
31
32void 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
60void 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
172status_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
210void 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
231void 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
249void 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
277bool 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
318void 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
465static 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
480static 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
702static 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
740void 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
789void 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
864status_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
898void 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
1234exit:
1235
1236    if ( NULL != frame )
1237        {
1238        delete frame;
1239        }
1240
1241    LOG_FUNCTION_NAME_EXIT;
1242}
1243
1244void 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
1252void 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
1280void 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
1300void 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
1308void 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
1342void AppCallbackNotifier::flushEventQueue()
1343{
1344
1345    {
1346    android::AutoMutex lock(mLock);
1347    mEventQ.clear();
1348    }
1349}
1350
1351
1352bool 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
1387AppCallbackNotifier::~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
1443void 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
1471void 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
1492void 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
1513status_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
1573void 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
1584void AppCallbackNotifier::useVideoBuffers(bool useVideoBuffers)
1585{
1586  LOG_FUNCTION_NAME;
1587
1588  mUseVideoBuffers = useVideoBuffers;
1589
1590  LOG_FUNCTION_NAME_EXIT;
1591}
1592
1593bool AppCallbackNotifier::getUesVideoBuffers()
1594{
1595    return mUseVideoBuffers;
1596}
1597
1598void 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
1608status_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
1640status_t AppCallbackNotifier::useMetaDataBufferMode(bool enable)
1641{
1642    mUseMetaDataBufferMode = enable;
1643
1644    return NO_ERROR;
1645}
1646
1647
1648status_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
1680status_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
1720exit:
1721    LOG_FUNCTION_NAME_EXIT;
1722
1723    return ret;
1724}
1725
1726status_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
1760status_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
1807status_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
1824status_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
1842status_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
1883status_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