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
31namespace android {
32
33const int AppCallbackNotifier::NOTIFIER_TIMEOUT = -1;
34KeyedVector<void*, sp<Encoder_libjpeg> > gEncoderQueue;
35
36void 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
63void 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
171status_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
202void 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
223void 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
241void 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
267bool 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
308void 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
453static 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
468static 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
690void 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
726void 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
799status_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
833void 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
1160exit:
1161
1162    if ( NULL != frame )
1163        {
1164        delete frame;
1165        }
1166
1167    LOG_FUNCTION_NAME_EXIT;
1168}
1169
1170void 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
1178void 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
1206void 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
1224void 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
1232void 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
1266void AppCallbackNotifier::flushEventQueue()
1267{
1268
1269    {
1270    Mutex::Autolock lock(mLock);
1271    mEventQ.clear();
1272    }
1273}
1274
1275
1276bool 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
1311AppCallbackNotifier::~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
1367void 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
1395void 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
1416void 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
1437status_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
1511void 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
1522void AppCallbackNotifier::useVideoBuffers(bool useVideoBuffers)
1523{
1524  LOG_FUNCTION_NAME;
1525
1526  mUseVideoBuffers = useVideoBuffers;
1527
1528  LOG_FUNCTION_NAME_EXIT;
1529}
1530
1531bool AppCallbackNotifier::getUesVideoBuffers()
1532{
1533    return mUseVideoBuffers;
1534}
1535
1536void 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
1546status_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
1579status_t AppCallbackNotifier::useMetaDataBufferMode(bool enable)
1580{
1581    mUseMetaDataBufferMode = enable;
1582
1583    return NO_ERROR;
1584}
1585
1586
1587status_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
1619status_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
1659exit:
1660    LOG_FUNCTION_NAME_EXIT;
1661
1662    return ret;
1663}
1664
1665status_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
1699status_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
1744status_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
1753status_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
1763status_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
1804status_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