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