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 "ANativeWindowDisplayAdapter.h"
18#include <OMX_IVCommon.h>
19#include <ui/GraphicBuffer.h>
20#include <ui/GraphicBufferMapper.h>
21#include <hal_public.h>
22
23namespace Ti {
24namespace Camera {
25
26///Constant declarations
27///@todo Check the time units
28const int ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT = 1000;  // seconds
29
30//Suspends buffers after given amount of failed dq's
31const int ANativeWindowDisplayAdapter::FAILED_DQS_TO_SUSPEND = 3;
32
33
34OMX_COLOR_FORMATTYPE toOMXPixFormat(const char* parameters_format)
35{
36    OMX_COLOR_FORMATTYPE pixFormat;
37
38    if ( parameters_format != NULL )
39    {
40        if (strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
41            {
42            CAMHAL_LOGDA("CbYCrY format selected");
43            pixFormat = OMX_COLOR_FormatCbYCrY;
44            }
45        else if(strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0)
46            {
47            CAMHAL_LOGDA("YUV420SP format selected");
48            pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
49            }
50        else if(strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_RGB565) == 0)
51            {
52            CAMHAL_LOGDA("RGB565 format selected");
53            pixFormat = OMX_COLOR_Format16bitRGB565;
54            }
55        else
56            {
57            CAMHAL_LOGDA("Invalid format, NV12 format selected as default");
58            pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
59        }
60    }
61    else {
62        CAMHAL_LOGEA("Preview format is NULL, defaulting to NV12");
63        pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
64    }
65
66    return pixFormat;
67}
68
69/*--------------------ANativeWindowDisplayAdapter Class STARTS here-----------------------------*/
70
71
72/**
73 * Display Adapter class STARTS here..
74 */
75ANativeWindowDisplayAdapter::ANativeWindowDisplayAdapter():mDisplayThread(NULL),
76                                        mDisplayState(ANativeWindowDisplayAdapter::DISPLAY_INIT),
77                                        mDisplayEnabled(false),
78                                        mBufferCount(0)
79
80
81
82{
83    LOG_FUNCTION_NAME;
84
85#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
86
87    mShotToShot = false;
88    mStartCapture.tv_sec = 0;
89    mStartCapture.tv_usec = 0;
90    mStandbyToShot.tv_sec = 0;
91    mStandbyToShot.tv_usec = 0;
92    mMeasureStandby = false;
93#endif
94
95    mPixelFormat = NULL;
96    mBuffers = NULL;
97    mOffsetsMap = NULL;
98    mFrameProvider = NULL;
99    mANativeWindow = NULL;
100
101    mFrameWidth = 0;
102    mFrameHeight = 0;
103    mPreviewWidth = 0;
104    mPreviewHeight = 0;
105
106    mSuspend = false;
107    mFailedDQs = 0;
108
109    mPaused = false;
110    mXOff = -1;
111    mYOff = -1;
112    mFirstInit = false;
113
114    mFD = -1;
115
116    LOG_FUNCTION_NAME_EXIT;
117}
118
119ANativeWindowDisplayAdapter::~ANativeWindowDisplayAdapter()
120{
121    Utils::Semaphore sem;
122    Utils::Message msg;
123
124    LOG_FUNCTION_NAME;
125
126    ///If Frame provider exists
127    if (mFrameProvider) {
128        // Unregister with the frame provider
129        mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES);
130        delete mFrameProvider;
131        mFrameProvider = NULL;
132    }
133
134    ///The ANativeWindow object will get destroyed here
135    destroy();
136
137    ///If Display thread exists
138    if(mDisplayThread.get())
139        {
140        ///Kill the display thread
141        sem.Create();
142        msg.command = DisplayThread::DISPLAY_EXIT;
143
144        // Send the semaphore to signal once the command is completed
145        msg.arg1 = &sem;
146
147        ///Post the message to display thread
148        mDisplayThread->msgQ().put(&msg);
149
150        ///Wait for the ACK - implies that the thread is now started and waiting for frames
151        sem.Wait();
152
153        // Exit and cleanup the thread
154        mDisplayThread->requestExitAndWait();
155
156        // Delete the display thread
157        mDisplayThread.clear();
158    }
159
160    LOG_FUNCTION_NAME_EXIT;
161
162}
163
164status_t ANativeWindowDisplayAdapter::initialize()
165{
166    LOG_FUNCTION_NAME;
167
168    ///Create the display thread
169    mDisplayThread = new DisplayThread(this);
170    if ( !mDisplayThread.get() )
171        {
172        CAMHAL_LOGEA("Couldn't create display thread");
173        LOG_FUNCTION_NAME_EXIT;
174        return NO_MEMORY;
175    }
176
177    ///Start the display thread
178    status_t ret = mDisplayThread->run("DisplayThread", android::PRIORITY_URGENT_DISPLAY);
179    if ( ret != NO_ERROR )
180        {
181        CAMHAL_LOGEA("Couldn't run display thread");
182        LOG_FUNCTION_NAME_EXIT;
183        return ret;
184    }
185
186    LOG_FUNCTION_NAME_EXIT;
187
188    return ret;
189}
190
191int ANativeWindowDisplayAdapter::setPreviewWindow(preview_stream_ops_t* window)
192{
193    LOG_FUNCTION_NAME;
194    ///Note that Display Adapter cannot work without a valid window object
195    if ( !window)
196        {
197        CAMHAL_LOGEA("NULL window object passed to DisplayAdapter");
198        LOG_FUNCTION_NAME_EXIT;
199        return BAD_VALUE;
200    }
201
202    if ( window == mANativeWindow ) {
203        return ALREADY_EXISTS;
204    }
205
206    ///Destroy the existing window object, if it exists
207    destroy();
208
209    ///Move to new window obj
210    mANativeWindow = window;
211
212    LOG_FUNCTION_NAME_EXIT;
213
214    return NO_ERROR;
215}
216
217int ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider)
218{
219    LOG_FUNCTION_NAME;
220
221    // Check for NULL pointer
222    if ( !frameProvider ) {
223        CAMHAL_LOGEA("NULL passed for frame provider");
224        LOG_FUNCTION_NAME_EXIT;
225        return BAD_VALUE;
226    }
227
228    //Release any previous frame providers
229    if ( NULL != mFrameProvider ) {
230        delete mFrameProvider;
231    }
232
233    /** Dont do anything here, Just save the pointer for use when display is
234         actually enabled or disabled
235    */
236    mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay);
237
238    LOG_FUNCTION_NAME_EXIT;
239
240    return NO_ERROR;
241}
242
243int ANativeWindowDisplayAdapter::setErrorHandler(ErrorNotifier *errorNotifier)
244{
245    status_t ret = NO_ERROR;
246
247    LOG_FUNCTION_NAME;
248
249    if ( NULL == errorNotifier ) {
250        CAMHAL_LOGEA("Invalid Error Notifier reference");
251        ret = BAD_VALUE;
252    }
253
254    if ( NO_ERROR == ret )
255        {
256        mErrorNotifier = errorNotifier;
257    }
258
259    LOG_FUNCTION_NAME_EXIT;
260
261    return ret;
262}
263
264#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
265
266status_t ANativeWindowDisplayAdapter::setSnapshotTimeRef(struct timeval *refTime)
267{
268    status_t ret = NO_ERROR;
269
270    LOG_FUNCTION_NAME;
271
272    if ( NULL != refTime )
273        {
274        android::AutoMutex lock(mLock);
275        memcpy(&mStartCapture, refTime, sizeof(struct timeval));
276    }
277
278    LOG_FUNCTION_NAME_EXIT;
279
280    return ret;
281}
282
283#endif
284
285
286int ANativeWindowDisplayAdapter::enableDisplay(int width, int height, struct timeval *refTime)
287{
288    Utils::Semaphore sem;
289    Utils::Message msg;
290
291    LOG_FUNCTION_NAME;
292
293    if ( mDisplayEnabled )
294        {
295        CAMHAL_LOGDA("Display is already enabled");
296        LOG_FUNCTION_NAME_EXIT;
297
298        return NO_ERROR;
299    }
300
301#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
302
303    if ( NULL != refTime )
304        {
305        android::AutoMutex lock(mLock);
306        memcpy(&mStandbyToShot, refTime, sizeof(struct timeval));
307        mMeasureStandby = true;
308    }
309
310#endif
311
312    //Send START_DISPLAY COMMAND to display thread. Display thread will start and then wait for a message
313    sem.Create();
314    msg.command = DisplayThread::DISPLAY_START;
315
316    // Send the semaphore to signal once the command is completed
317    msg.arg1 = &sem;
318
319    ///Post the message to display thread
320    mDisplayThread->msgQ().put(&msg);
321
322    ///Wait for the ACK - implies that the thread is now started and waiting for frames
323    sem.Wait();
324
325    // Register with the frame provider for frames
326    mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
327    mFrameProvider->enableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
328
329    mDisplayEnabled = true;
330    mPreviewWidth = width;
331    mPreviewHeight = height;
332
333    CAMHAL_LOGVB("mPreviewWidth = %d mPreviewHeight = %d", mPreviewWidth, mPreviewHeight);
334
335    LOG_FUNCTION_NAME_EXIT;
336
337    return NO_ERROR;
338}
339
340int ANativeWindowDisplayAdapter::disableDisplay(bool cancel_buffer)
341{
342    status_t ret = NO_ERROR;
343    android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
344
345    LOG_FUNCTION_NAME;
346
347    if(!mDisplayEnabled)
348        {
349        CAMHAL_LOGDA("Display is already disabled");
350        LOG_FUNCTION_NAME_EXIT;
351        return ALREADY_EXISTS;
352    }
353
354    // Unregister with the frame provider here
355    mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
356    mFrameProvider->disableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
357    mFrameProvider->removeFramePointers();
358
359    if ( NULL != mDisplayThread.get() )
360        {
361        //Send STOP_DISPLAY COMMAND to display thread. Display thread will stop and dequeue all messages
362        // and then wait for message
363        Utils::Semaphore sem;
364        sem.Create();
365        Utils::Message msg;
366        msg.command = DisplayThread::DISPLAY_STOP;
367
368        // Send the semaphore to signal once the command is completed
369        msg.arg1 = &sem;
370
371        ///Post the message to display thread
372        mDisplayThread->msgQ().put(&msg);
373
374        ///Wait for the ACK for display to be disabled
375
376        sem.Wait();
377
378    }
379
380    android::AutoMutex lock(mLock);
381    {
382        ///Reset the display enabled flag
383        mDisplayEnabled = false;
384
385        // Reset pause flag since display is being disabled
386        mPaused = false;
387
388        ///Reset the offset values
389        mXOff = -1;
390        mYOff = -1;
391
392        ///Reset the frame width and height values
393        mFrameWidth =0;
394        mFrameHeight = 0;
395        mPreviewWidth = 0;
396        mPreviewHeight = 0;
397
398       if(cancel_buffer)
399        {
400        // Return the buffers to ANativeWindow here, the mFramesWithCameraAdapterMap is also cleared inside
401        returnBuffersToWindow();
402        }
403       else
404        {
405        mANativeWindow = NULL;
406        // Clear the frames with camera adapter map
407        mFramesWithCameraAdapterMap.clear();
408        }
409
410
411    }
412    LOG_FUNCTION_NAME_EXIT;
413
414    return NO_ERROR;
415}
416
417status_t ANativeWindowDisplayAdapter::pauseDisplay(bool pause)
418{
419    status_t ret = NO_ERROR;
420
421    LOG_FUNCTION_NAME;
422
423    {
424        android::AutoMutex lock(mLock);
425        mPaused = pause;
426    }
427
428    LOG_FUNCTION_NAME_EXIT;
429
430    return ret;
431}
432
433
434void ANativeWindowDisplayAdapter::destroy()
435{
436    LOG_FUNCTION_NAME;
437
438    ///Check if the display is disabled, if not disable it
439    if ( mDisplayEnabled )
440    {
441        CAMHAL_LOGDA("WARNING: Calling destroy of Display adapter when display enabled. Disabling display..");
442        disableDisplay(false);
443    }
444
445    mBufferCount = 0;
446
447    LOG_FUNCTION_NAME_EXIT;
448}
449
450// Implementation of inherited interfaces
451CameraBuffer* ANativeWindowDisplayAdapter::allocateBufferList(int width, int height, const char* format, int &bytes, int numBufs)
452{
453    LOG_FUNCTION_NAME;
454    status_t err;
455    int i = -1;
456    const int lnumBufs = numBufs;
457    int undequeued = 0;
458    android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
459    android::Rect bounds;
460
461    mBuffers = new CameraBuffer [lnumBufs];
462    memset (mBuffers, 0, sizeof(CameraBuffer) * lnumBufs);
463
464    mFramesType.clear();
465
466    if ( NULL == mANativeWindow ) {
467        return NULL;
468    }
469
470    // Set gralloc usage bits for window.
471    err = mANativeWindow->set_usage(mANativeWindow, CAMHAL_GRALLOC_USAGE);
472    if ( NO_ERROR != err ) {
473        CAMHAL_LOGE("Surface::setUsage failed: %s (%d)", strerror(-err), -err);
474
475        if ( NO_INIT == err ) {
476            CAMHAL_LOGEA("Preview surface abandoned!");
477            mANativeWindow = NULL;
478        }
479
480        return NULL;
481    }
482
483    CAMHAL_LOGDB("Number of buffers set to ANativeWindow %d", numBufs);
484    ///Set the number of buffers needed for camera preview
485    err = mANativeWindow->set_buffer_count(mANativeWindow, numBufs);
486    if ( NO_ERROR != err ) {
487        CAMHAL_LOGE("Surface::setBufferCount failed: %s (%d)", strerror(-err), -err);
488
489        if ( NO_INIT == err ) {
490            CAMHAL_LOGEA("Preview surface abandoned!");
491            mANativeWindow = NULL;
492        }
493
494        return NULL;
495    }
496    CAMHAL_LOGDB("Configuring %d buffers for ANativeWindow", numBufs);
497    mBufferCount = numBufs;
498
499
500    // Set window geometry
501    err = mANativeWindow->set_buffers_geometry(
502            mANativeWindow,
503            width,
504            height,
505            /*toOMXPixFormat(format)*/HAL_PIXEL_FORMAT_TI_NV12);  // Gralloc only supports NV12 alloc!
506
507    if ( NO_ERROR != err ) {
508        CAMHAL_LOGE("native_window_set_buffers_geometry failed: %s (%d)", strerror(-err), -err);
509
510        if ( NO_INIT == err ) {
511            CAMHAL_LOGEA("Preview surface abandoned!");
512            mANativeWindow = NULL;
513        }
514
515        return NULL;
516    }
517
518    ///We just return the buffers from ANativeWindow, if the width and height are same, else (vstab, vnf case)
519    ///re-allocate buffers using ANativeWindow and then get them
520    ///@todo - Re-allocate buffers for vnf and vstab using the width, height, format, numBufs etc
521    if ( mBuffers == NULL )
522    {
523        CAMHAL_LOGEA("Couldn't create array for ANativeWindow buffers");
524        LOG_FUNCTION_NAME_EXIT;
525        return NULL;
526    }
527
528    mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued);
529    mPixelFormat = CameraHal::getPixelFormatConstant(format);
530
531    for ( i=0; i < mBufferCount; i++ )
532    {
533        buffer_handle_t *handle;
534        int stride;  // dummy variable to get stride
535        // TODO(XXX): Do we need to keep stride information in camera hal?
536
537        err = mANativeWindow->dequeue_buffer(mANativeWindow, &handle, &stride);
538
539        if ( NO_ERROR != err ) {
540            CAMHAL_LOGE("Surface::dequeueBuffer failed: %s (%d)", strerror(-err), -err);
541
542            if ( NO_INIT == err ) {
543                CAMHAL_LOGEA("Preview surface abandoned!");
544                mANativeWindow = NULL;
545            }
546
547            goto fail;
548        }
549
550        CAMHAL_LOGDB("got handle %p", handle);
551        mBuffers[i].opaque = (void *)handle;
552        mBuffers[i].type = CAMERA_BUFFER_ANW;
553        mBuffers[i].format = mPixelFormat;
554        mFramesWithCameraAdapterMap.add(handle, i);
555
556        // Tag remaining preview buffers as preview frames
557        if ( i >= ( mBufferCount - undequeued ) ) {
558            mFramesType.add( (int) mBuffers[i].opaque,
559                            CameraFrame::PREVIEW_FRAME_SYNC);
560        }
561
562        bytes = CameraHal::calculateBufferSize(format, width, height);
563
564    }
565
566    // lock the initial queueable buffers
567    bounds.left = 0;
568    bounds.top = 0;
569    bounds.right = width;
570    bounds.bottom = height;
571
572    for( i = 0;  i < mBufferCount-undequeued; i++ )
573    {
574        void *y_uv[2];
575        buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
576
577        mANativeWindow->lock_buffer(mANativeWindow, handle);
578
579        mapper.lock(*handle, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
580        mBuffers[i].mapped = y_uv[0];
581        mFrameProvider->addFramePointers(&mBuffers[i], y_uv);
582    }
583
584    // return the rest of the buffers back to ANativeWindow
585    for(i = (mBufferCount-undequeued); i >= 0 && i < mBufferCount; i++)
586    {
587        buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
588        err = mANativeWindow->cancel_buffer(mANativeWindow, handle);
589        if ( NO_ERROR != err ) {
590            CAMHAL_LOGE("Surface::cancelBuffer failed: %s (%d)", strerror(-err), -err);
591
592            if ( NO_INIT == err ) {
593                CAMHAL_LOGEA("Preview surface abandoned!");
594                mANativeWindow = NULL;
595            }
596
597            goto fail;
598        }
599        mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) mBuffers[i].opaque);
600        //LOCK UNLOCK TO GET YUV POINTERS
601        void *y_uv[2];
602        mapper.lock(*(buffer_handle_t *) mBuffers[i].opaque, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
603        mBuffers[i].mapped = y_uv[0];
604        mFrameProvider->addFramePointers(&mBuffers[i], y_uv);
605        mapper.unlock(*(buffer_handle_t *) mBuffers[i].opaque);
606    }
607
608    mFirstInit = true;
609    mFrameWidth = width;
610    mFrameHeight = height;
611
612    return mBuffers;
613
614 fail:
615    // need to cancel buffers if any were dequeued
616    for (int start = 0; start < i && i > 0; start++) {
617        status_t err = mANativeWindow->cancel_buffer(mANativeWindow,
618                (buffer_handle_t *) mBuffers[start].opaque);
619        if ( NO_ERROR != err ) {
620          CAMHAL_LOGE("Surface::cancelBuffer failed w/ error 0x%08x", err);
621          break;
622        }
623        mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) mBuffers[start].opaque);
624    }
625
626    freeBufferList(mBuffers);
627
628    CAMHAL_LOGEA("Error occurred, performing cleanup");
629
630    if ( NULL != mErrorNotifier.get() ) {
631        mErrorNotifier->errorNotify(NO_MEMORY);
632    }
633
634    LOG_FUNCTION_NAME_EXIT;
635    return NULL;
636
637}
638
639CameraBuffer* ANativeWindowDisplayAdapter::getBufferList(int *numBufs) {
640    LOG_FUNCTION_NAME;
641    if (numBufs) *numBufs = -1;
642
643    return NULL;
644}
645
646uint32_t * ANativeWindowDisplayAdapter::getOffsets()
647{
648    const int lnumBufs = mBufferCount;
649
650    LOG_FUNCTION_NAME;
651
652    // TODO(XXX): Need to remove getOffsets from the API. No longer needed
653
654    if ( NULL == mANativeWindow )
655    {
656        CAMHAL_LOGEA("mANativeWindow reference is missing");
657        goto fail;
658    }
659
660    if( mBuffers == NULL)
661    {
662        CAMHAL_LOGEA("Buffers not allocated yet!!");
663        goto fail;
664    }
665
666    if(mOffsetsMap == NULL)
667    {
668        mOffsetsMap = new uint32_t[lnumBufs];
669        for(int i = 0; i < mBufferCount; i++)
670        {
671            mOffsetsMap[i] = 0;
672        }
673    }
674
675    LOG_FUNCTION_NAME_EXIT;
676
677    return mOffsetsMap;
678
679 fail:
680
681    if ( NULL != mOffsetsMap )
682    {
683        delete [] mOffsetsMap;
684        mOffsetsMap = NULL;
685    }
686
687    if ( NULL != mErrorNotifier.get() ) {
688        mErrorNotifier->errorNotify(INVALID_OPERATION);
689    }
690
691    LOG_FUNCTION_NAME_EXIT;
692
693    return NULL;
694}
695
696status_t ANativeWindowDisplayAdapter::minUndequeueableBuffers(int& undequeueable) {
697    LOG_FUNCTION_NAME;
698    status_t ret = NO_ERROR;
699
700    if(!mANativeWindow) {
701        ret = INVALID_OPERATION;
702        goto end;
703    }
704
705    ret = mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeueable);
706    if ( NO_ERROR != ret ) {
707        CAMHAL_LOGEB("get_min_undequeued_buffer_count failed: %s (%d)", strerror(-ret), -ret);
708
709        if ( NO_INIT == ret ) {
710            CAMHAL_LOGEA("Preview surface abandoned!");
711            mANativeWindow = NULL;
712        }
713
714        return ret;
715    }
716
717 end:
718    return ret;
719    LOG_FUNCTION_NAME_EXIT;
720
721}
722
723status_t ANativeWindowDisplayAdapter::maxQueueableBuffers(unsigned int& queueable)
724{
725    LOG_FUNCTION_NAME;
726    status_t ret = NO_ERROR;
727    int undequeued = 0;
728
729    if(mBufferCount == 0)
730    {
731        ret = INVALID_OPERATION;
732        goto end;
733    }
734
735    ret = minUndequeueableBuffers(undequeued);
736    if (ret != NO_ERROR) {
737        goto end;
738    }
739
740    queueable = mBufferCount - undequeued;
741
742 end:
743    return ret;
744    LOG_FUNCTION_NAME_EXIT;
745}
746
747int ANativeWindowDisplayAdapter::getFd()
748{
749    LOG_FUNCTION_NAME;
750
751    if(mFD == -1)
752    {
753        buffer_handle_t *handle =  (buffer_handle_t *)mBuffers[0].opaque;
754        IMG_native_handle_t *img = (IMG_native_handle_t *)handle;
755        // TODO: should we dup the fd? not really necessary and another thing for ANativeWindow
756        // to manage and close...
757
758        mFD = dup(img->fd[0]);
759    }
760
761    LOG_FUNCTION_NAME_EXIT;
762
763    return mFD;
764
765}
766
767status_t ANativeWindowDisplayAdapter::returnBuffersToWindow()
768{
769    status_t ret = NO_ERROR;
770
771     android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
772    //Give the buffers back to display here -  sort of free it
773     if (mANativeWindow)
774         for(unsigned int i = 0; i < mFramesWithCameraAdapterMap.size(); i++) {
775             int value = mFramesWithCameraAdapterMap.valueAt(i);
776             buffer_handle_t *handle = (buffer_handle_t *) mBuffers[value].opaque;
777
778             // if buffer index is out of bounds skip
779             if ((value < 0) || (value >= mBufferCount)) {
780                 CAMHAL_LOGEA("Potential out bounds access to handle...skipping");
781                 continue;
782             }
783
784             // unlock buffer before giving it up
785             mapper.unlock(*handle);
786
787             ret = mANativeWindow->cancel_buffer(mANativeWindow, handle);
788             if ( NO_INIT == ret ) {
789                 CAMHAL_LOGEA("Preview surface abandoned!");
790                 mANativeWindow = NULL;
791                 return ret;
792             } else if ( NO_ERROR != ret ) {
793                 CAMHAL_LOGE("Surface::cancelBuffer() failed: %s (%d)",
794                              strerror(-ret),
795                              -ret);
796                return ret;
797             }
798         }
799     else
800         CAMHAL_LOGE("mANativeWindow is NULL");
801
802     ///Clear the frames with camera adapter map
803     mFramesWithCameraAdapterMap.clear();
804
805     return ret;
806
807}
808
809int ANativeWindowDisplayAdapter::freeBufferList(CameraBuffer * buflist)
810{
811    LOG_FUNCTION_NAME;
812
813    status_t ret = NO_ERROR;
814
815    android::AutoMutex lock(mLock);
816
817    if(mBuffers != buflist)
818    {
819        CAMHAL_LOGEA("CameraHal passed wrong set of buffers to free!!!");
820        if (mBuffers != NULL)
821            delete []mBuffers;
822        mBuffers = NULL;
823    }
824
825    /* FIXME this will probably want the list that was just deleted */
826    returnBuffersToWindow();
827
828    if ( NULL != buflist )
829    {
830        delete [] buflist;
831        mBuffers = NULL;
832    }
833
834    if( mBuffers != NULL)
835    {
836        delete [] mBuffers;
837        mBuffers = NULL;
838    }
839
840    if ( NULL != mOffsetsMap )
841    {
842        delete [] mOffsetsMap;
843        mOffsetsMap = NULL;
844    }
845
846    if( mFD != -1)
847    {
848        close(mFD);  // close duped handle
849        mFD = -1;
850    }
851
852    mFramesType.clear();
853
854    return NO_ERROR;
855}
856
857
858bool ANativeWindowDisplayAdapter::supportsExternalBuffering()
859{
860    return false;
861}
862
863void ANativeWindowDisplayAdapter::displayThread()
864{
865    bool shouldLive = true;
866    int timeout = 0;
867    status_t ret;
868
869    LOG_FUNCTION_NAME;
870
871    while(shouldLive)
872        {
873        ret = Utils::MessageQueue::waitForMsg(&mDisplayThread->msgQ()
874                                                                ,  &mDisplayQ
875                                                                , NULL
876                                                                , ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT);
877
878        if ( !mDisplayThread->msgQ().isEmpty() )
879            {
880            ///Received a message from CameraHal, process it
881            shouldLive = processHalMsg();
882
883            }
884        else  if( !mDisplayQ.isEmpty())
885            {
886            if ( mDisplayState== ANativeWindowDisplayAdapter::DISPLAY_INIT )
887                {
888
889                ///If display adapter is not started, continue
890                continue;
891
892                }
893            else
894                {
895                Utils::Message msg;
896                ///Get the dummy msg from the displayQ
897                if(mDisplayQ.get(&msg)!=NO_ERROR)
898                    {
899                    CAMHAL_LOGEA("Error in getting message from display Q");
900                    continue;
901                }
902
903                // There is a frame from ANativeWindow for us to dequeue
904                // We dequeue and return the frame back to Camera adapter
905                if(mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED)
906                {
907                    handleFrameReturn();
908                }
909
910                if (mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_EXITED)
911                    {
912                    ///we exit the thread even though there are frames still to dequeue. They will be dequeued
913                    ///in disableDisplay
914                    shouldLive = false;
915                }
916            }
917        }
918    }
919
920    LOG_FUNCTION_NAME_EXIT;
921}
922
923
924bool ANativeWindowDisplayAdapter::processHalMsg()
925{
926    Utils::Message msg;
927
928    LOG_FUNCTION_NAME;
929
930
931    mDisplayThread->msgQ().get(&msg);
932    bool ret = true, invalidCommand = false;
933
934    switch ( msg.command )
935        {
936
937        case DisplayThread::DISPLAY_START:
938
939            CAMHAL_LOGDA("Display thread received DISPLAY_START command from Camera HAL");
940            mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STARTED;
941
942            break;
943
944        case DisplayThread::DISPLAY_STOP:
945
946            ///@bug There is no API to disable SF without destroying it
947            ///@bug Buffers might still be w/ display and will get displayed
948            ///@remarks Ideal seqyence should be something like this
949            ///mOverlay->setParameter("enabled", false);
950            CAMHAL_LOGDA("Display thread received DISPLAY_STOP command from Camera HAL");
951            mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STOPPED;
952
953            // flush frame message queue
954            while ( !mDisplayQ.isEmpty() ) {
955                Utils::Message message;
956                mDisplayQ.get(&message);
957            }
958
959            break;
960
961        case DisplayThread::DISPLAY_EXIT:
962
963            CAMHAL_LOGDA("Display thread received DISPLAY_EXIT command from Camera HAL.");
964            CAMHAL_LOGDA("Stopping display thread...");
965            mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_EXITED;
966            ///Note that the SF can have pending buffers when we disable the display
967            ///This is normal and the expectation is that they may not be displayed.
968            ///This is to ensure that the user experience is not impacted
969            ret = false;
970            break;
971
972        default:
973
974            CAMHAL_LOGEB("Invalid Display Thread Command 0x%x.", msg.command);
975            invalidCommand = true;
976
977            break;
978    }
979
980    ///Signal the semaphore if it is sent as part of the message
981    if ( ( msg.arg1 ) && ( !invalidCommand ) )
982        {
983
984        CAMHAL_LOGDA("+Signalling display semaphore");
985        Utils::Semaphore &sem = *((Utils::Semaphore*)msg.arg1);
986
987        sem.Signal();
988
989        CAMHAL_LOGDA("-Signalling display semaphore");
990    }
991
992
993    LOG_FUNCTION_NAME_EXIT;
994    return ret;
995}
996
997
998status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame)
999{
1000    status_t ret = NO_ERROR;
1001    uint32_t actualFramesWithDisplay = 0;
1002    android_native_buffer_t *buffer = NULL;
1003    android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
1004    int i;
1005
1006    ///@todo Do cropping based on the stabilized frame coordinates
1007    ///@todo Insert logic to drop frames here based on refresh rate of
1008    ///display or rendering rate whichever is lower
1009    ///Queue the buffer to overlay
1010
1011    if ( NULL == mANativeWindow ) {
1012        return NO_INIT;
1013    }
1014
1015    if (!mBuffers || !dispFrame.mBuffer) {
1016        CAMHAL_LOGEA("NULL sent to PostFrame");
1017        return BAD_VALUE;
1018    }
1019
1020    for ( i = 0; i < mBufferCount; i++ )
1021    {
1022        if ( dispFrame.mBuffer == &mBuffers[i] )
1023        {
1024            break;
1025        }
1026    }
1027
1028#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
1029
1030    if ( mMeasureStandby ) {
1031        CameraHal::PPM("Standby to first shot: Sensor Change completed - ", &mStandbyToShot);
1032        mMeasureStandby = false;
1033    } else if (CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) {
1034        CameraHal::PPM("Shot to snapshot: ", &mStartCapture);
1035        mShotToShot = true;
1036    } else if ( mShotToShot ) {
1037        CameraHal::PPM("Shot to shot: ", &mStartCapture);
1038        mShotToShot = false;
1039    }
1040
1041#endif
1042
1043    android::AutoMutex lock(mLock);
1044
1045    mFramesType.add( (int)mBuffers[i].opaque, dispFrame.mType);
1046
1047    if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED &&
1048                (!mPaused ||  CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) &&
1049                !mSuspend)
1050    {
1051        uint32_t xOff, yOff;
1052
1053        CameraHal::getXYFromOffset(&xOff, &yOff, dispFrame.mOffset, PAGE_SIZE, mPixelFormat);
1054
1055        // Set crop only if current x and y offsets do not match with frame offsets
1056        if ((mXOff != xOff) || (mYOff != yOff)) {
1057            CAMHAL_LOGDB("offset = %u left = %d top = %d right = %d bottom = %d",
1058                          dispFrame.mOffset, xOff, yOff ,
1059                          xOff + mPreviewWidth, yOff + mPreviewHeight);
1060
1061            // We'll ignore any errors here, if the surface is
1062            // already invalid, we'll know soon enough.
1063            mANativeWindow->set_crop(mANativeWindow, xOff, yOff,
1064                                     xOff + mPreviewWidth, yOff + mPreviewHeight);
1065
1066            // Update the current x and y offsets
1067            mXOff = xOff;
1068            mYOff = yOff;
1069        }
1070
1071        {
1072            buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
1073            // unlock buffer before sending to display
1074            mapper.unlock(*handle);
1075            ret = mANativeWindow->enqueue_buffer(mANativeWindow, handle);
1076        }
1077        if ( NO_ERROR != ret ) {
1078            CAMHAL_LOGE("Surface::queueBuffer returned error %d", ret);
1079        }
1080
1081        mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) dispFrame.mBuffer->opaque);
1082
1083
1084        // HWComposer has not minimum buffer requirement. We should be able to dequeue
1085        // the buffer immediately
1086        Utils::Message msg;
1087        mDisplayQ.put(&msg);
1088
1089    }
1090    else
1091    {
1092        buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
1093
1094        // unlock buffer before giving it up
1095        mapper.unlock(*handle);
1096
1097        // cancel buffer and dequeue another one
1098        ret = mANativeWindow->cancel_buffer(mANativeWindow, handle);
1099        if ( NO_ERROR != ret ) {
1100            CAMHAL_LOGE("Surface::cancelBuffer returned error %d", ret);
1101        }
1102
1103        mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) dispFrame.mBuffer->opaque);
1104
1105        Utils::Message msg;
1106        mDisplayQ.put(&msg);
1107        ret = NO_ERROR;
1108    }
1109
1110    return ret;
1111}
1112
1113
1114bool ANativeWindowDisplayAdapter::handleFrameReturn()
1115{
1116    status_t err;
1117    buffer_handle_t *buf;
1118    int i = 0;
1119    unsigned int k;
1120    int stride;  // dummy variable to get stride
1121    android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
1122    android::Rect bounds;
1123    CameraFrame::FrameType frameType = CameraFrame::PREVIEW_FRAME_SYNC;
1124
1125    void *y_uv[2];
1126
1127    // TODO(XXX): Do we need to keep stride information in camera hal?
1128
1129    if ( NULL == mANativeWindow ) {
1130        return false;
1131    }
1132
1133    err = mANativeWindow->dequeue_buffer(mANativeWindow, &buf, &stride);
1134    if (err != 0) {
1135        CAMHAL_LOGE("Surface::dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1136
1137        if ( NO_INIT == err ) {
1138            CAMHAL_LOGEA("Preview surface abandoned!");
1139            mANativeWindow = NULL;
1140        }
1141
1142        return false;
1143    }
1144
1145    err = mANativeWindow->lock_buffer(mANativeWindow, buf);
1146    if ( NO_ERROR != err ) {
1147        CAMHAL_LOGE("Surface::lockBuffer failed: %s (%d)", strerror(-err), -err);
1148
1149        if ( NO_INIT == err ) {
1150            CAMHAL_LOGEA("Preview surface abandoned!");
1151            mANativeWindow = NULL;
1152        }
1153
1154        return false;
1155    }
1156
1157    for(i = 0; i < mBufferCount; i++)
1158    {
1159        if (mBuffers[i].opaque == buf)
1160            break;
1161    }
1162    if (i == mBufferCount) {
1163        CAMHAL_LOGEB("Failed to find handle %p", buf);
1164    }
1165
1166    // lock buffer before sending to FrameProvider for filling
1167    bounds.left = 0;
1168    bounds.top = 0;
1169    bounds.right = mFrameWidth;
1170    bounds.bottom = mFrameHeight;
1171
1172    int lock_try_count = 0;
1173    while (mapper.lock(*(buffer_handle_t *) mBuffers[i].opaque, CAMHAL_GRALLOC_USAGE, bounds, y_uv) < 0){
1174      if (++lock_try_count > LOCK_BUFFER_TRIES){
1175        if ( NULL != mErrorNotifier.get() ){
1176          mErrorNotifier->errorNotify(CAMERA_ERROR_UNKNOWN);
1177        }
1178        return false;
1179      }
1180      CAMHAL_LOGEA("Gralloc Lock FrameReturn Error: Sleeping 15ms");
1181      usleep(15000);
1182    }
1183
1184    {
1185        android::AutoMutex lock(mLock);
1186        mFramesWithCameraAdapterMap.add((buffer_handle_t *) mBuffers[i].opaque, i);
1187
1188        for( k = 0; k < mFramesType.size() ; k++) {
1189            if(mFramesType.keyAt(k) == (int)mBuffers[i].opaque)
1190                break;
1191        }
1192
1193        if ( k == mFramesType.size() ) {
1194            CAMHAL_LOGE("Frame type for preview buffer 0%x not found!!", mBuffers[i].opaque);
1195            return false;
1196        }
1197
1198        frameType = (CameraFrame::FrameType) mFramesType.valueAt(k);
1199        mFramesType.removeItem((int) mBuffers[i].opaque);
1200    }
1201
1202    CAMHAL_LOGVB("handleFrameReturn: found graphic buffer %d of %d", i, mBufferCount-1);
1203    mFrameProvider->returnFrame(&mBuffers[i], frameType);
1204
1205    return true;
1206}
1207
1208void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame)
1209{
1210
1211    if ( NULL != caFrame )
1212        {
1213        if ( NULL != caFrame->mCookie )
1214            {
1215            ANativeWindowDisplayAdapter *da = (ANativeWindowDisplayAdapter*) caFrame->mCookie;
1216            da->frameCallback(caFrame);
1217        }
1218        else
1219            {
1220            CAMHAL_LOGEB("Invalid Cookie in Camera Frame = %p, Cookie = %p", caFrame, caFrame->mCookie);
1221            }
1222        }
1223    else
1224        {
1225        CAMHAL_LOGEB("Invalid Camera Frame = %p", caFrame);
1226    }
1227
1228}
1229
1230void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame)
1231{
1232    ///Call queueBuffer of overlay in the context of the callback thread
1233
1234    DisplayFrame df;
1235    df.mBuffer = caFrame->mBuffer;
1236    df.mType = (CameraFrame::FrameType) caFrame->mFrameType;
1237    df.mOffset = caFrame->mOffset;
1238    df.mWidthStride = caFrame->mAlignment;
1239    df.mLength = caFrame->mLength;
1240    df.mWidth = caFrame->mWidth;
1241    df.mHeight = caFrame->mHeight;
1242    PostFrame(df);
1243}
1244
1245
1246/*--------------------ANativeWindowDisplayAdapter Class ENDS here-----------------------------*/
1247
1248} // namespace Camera
1249} // namespace Ti
1250