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