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