ANativeWindowDisplayAdapter.cpp revision c322989ae6ff6769490828de1b5eda12b749cce9
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_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
520            | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
521    if (err != 0) {
522        LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
523        return NULL;
524    }
525
526    CAMHAL_LOGDB("Number of buffers set to ANativeWindow %d", numBufs);
527    //if(mBufferCount != numBufs)
528    //    {
529        ///Set the number of buffers needed for camera preview
530        err = mANativeWindow->set_buffer_count(mANativeWindow, numBufs);
531        if (err != 0) {
532            LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err);
533            return NULL;
534        }
535        CAMHAL_LOGDB("Configuring %d buffers for ANativeWindow", numBufs);
536        mBufferCount = numBufs;
537    //}
538
539    // Set window geometry
540    err = mANativeWindow->set_buffers_geometry(
541            mANativeWindow,
542            width,
543            height,
544            /*toOMXPixFormat(format)*/HAL_PIXEL_FORMAT_NV12);  // Gralloc only supports NV12 alloc!
545
546    if (err != 0) {
547        LOGE("native_window_set_buffers_geometry failed: %s (%d)", strerror(-err), -err);
548        return NULL;
549    }
550
551    ///We just return the buffers from ANativeWindow, if the width and height are same, else (vstab, vnf case)
552    ///re-allocate buffers using ANativeWindow and then get them
553    ///@todo - Re-allocate buffers for vnf and vstab using the width, height, format, numBufs etc
554    if ( (buffers == NULL) || (mBufferHandleMap == NULL) )
555    {
556        CAMHAL_LOGEA("Couldn't create array for ANativeWindow buffers");
557        LOG_FUNCTION_NAME_EXIT;
558        delete [] buffers;
559        return NULL;
560    }
561
562    mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued);
563
564    for ( i=0; i < mBufferCount; i++ )
565    {
566        IMG_native_handle_t** hndl2hndl;
567        IMG_native_handle_t* handle;
568        int stride;  // dummy variable to get stride
569        // TODO(XXX): Do we need to keep stride information in camera hal?
570
571        err = mANativeWindow->dequeue_buffer(mANativeWindow, (buffer_handle_t**) &hndl2hndl, &stride);
572
573        if (err != 0) {
574            CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
575            goto fail;
576        }
577
578        handle = *hndl2hndl;
579
580        mBufferHandleMap[i] = (buffer_handle_t*) hndl2hndl;
581        mGrallocHandleMap[i] = handle;
582        mFramesWithCameraAdapterMap.add((int) mGrallocHandleMap[i], i);
583
584        bytes =  getBufSize(format, width, height);
585
586        CAMHAL_LOGDB("Adding buffer index=%d, address=0x%x", i, buffers[i]);
587    }
588
589
590    // lock the initial queueable buffers
591    for( i = 0;  i < mBufferCount-undequeued; i++ )
592    {
593        mANativeWindow->lock_buffer(mANativeWindow, mBufferHandleMap[i]);
594    }
595
596    // return the rest of the buffers back to ANativeWindow
597    for(i = (mBufferCount-undequeued); i >= 0 && i < mBufferCount; i++)
598    {
599        mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]);
600    }
601
602    mFirstInit = true;
603    mPixelFormat = getPixFormatConstant(format);
604    mFrameWidth = width;
605    mFrameHeight = height;
606
607    return mGrallocHandleMap;
608
609 fail:
610    // need to cancel buffers if any were dequeued
611    for (int start = 0; start < i && i > 0; start++) {
612        int err = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[start]);
613        if (err != 0) {
614          CAMHAL_LOGEB("cancelBuffer failed w/ error 0x%08x", err);
615        }
616    }
617    CAMHAL_LOGEA("Error occurred, performing cleanup");
618    if ( buffers )
619        {
620        delete [] buffers;
621    }
622
623    if ( NULL != mErrorNotifier.get() )
624        {
625        mErrorNotifier->errorNotify(-ENOMEM);
626    }
627
628    LOG_FUNCTION_NAME_EXIT;
629    return NULL;
630
631}
632
633uint32_t * ANativeWindowDisplayAdapter::getOffsets()
634{
635    const int lnumBufs = mBufferCount;
636
637    LOG_FUNCTION_NAME;
638
639    // TODO(XXX): Need to remove getOffsets from the API. No longer needed
640
641    if ( NULL == mANativeWindow )
642    {
643        CAMHAL_LOGEA("mANativeWindow reference is missing");
644        goto fail;
645    }
646
647    if( mBufferHandleMap == NULL)
648    {
649        CAMHAL_LOGEA("Buffers not allocated yet!!");
650        goto fail;
651    }
652
653    if(mOffsetsMap == NULL)
654    {
655        mOffsetsMap = new uint32_t[lnumBufs];
656        for(int i = 0; i < mBufferCount; i++)
657        {
658            IMG_native_handle_t* handle =  (IMG_native_handle_t*) *(mBufferHandleMap[i]);
659            mOffsetsMap[i] = 0;
660        }
661    }
662
663    LOG_FUNCTION_NAME_EXIT;
664
665    return mOffsetsMap;
666
667 fail:
668
669    if ( NULL != mOffsetsMap )
670    {
671        delete [] mOffsetsMap;
672        mOffsetsMap = NULL;
673    }
674
675    if ( NULL != mErrorNotifier.get() )
676    {
677        mErrorNotifier->errorNotify(-ENOSYS);
678    }
679
680    LOG_FUNCTION_NAME_EXIT;
681
682    return NULL;
683}
684
685int ANativeWindowDisplayAdapter::maxQueueableBuffers(unsigned int& queueable)
686{
687    LOG_FUNCTION_NAME;
688    int ret = NO_ERROR;
689    int undequeued = 0;
690
691    if(mBufferCount == 0)
692    {
693        ret = -ENOSYS;
694        goto end;
695    }
696
697    if(!mANativeWindow)
698    {
699        ret = -ENOSYS;
700        goto end;
701    }
702
703    mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued);
704
705    queueable = mBufferCount - undequeued;
706
707 end:
708    return ret;
709    LOG_FUNCTION_NAME_EXIT;
710}
711
712int ANativeWindowDisplayAdapter::getFd()
713{
714    LOG_FUNCTION_NAME;
715
716    if(mFD == -1)
717    {
718        IMG_native_handle_t* handle =  (IMG_native_handle_t*) *(mBufferHandleMap[0]);
719        // TODO: should we dup the fd? not really necessary and another thing for ANativeWindow
720        // to manage and close...
721        mFD = dup(handle->fd[0]);
722    }
723
724    LOG_FUNCTION_NAME_EXIT;
725
726    return mFD;
727
728}
729
730int ANativeWindowDisplayAdapter::freeBuffer(void* buf)
731{
732    LOG_FUNCTION_NAME;
733
734    int *buffers = (int *) buf;
735    if((int *)mGrallocHandleMap != buffers)
736    {
737        CAMHAL_LOGEA("CameraHal passed wrong set of buffers to free!!!");
738        if (mGrallocHandleMap != NULL)
739            delete []mGrallocHandleMap;
740        mGrallocHandleMap = NULL;
741    }
742
743    if ( NULL != buf )
744    {
745        delete [] buffers;
746    }
747
748    if( mBufferHandleMap != NULL)
749    {
750        delete [] mBufferHandleMap;
751        mBufferHandleMap = NULL;
752    }
753
754    if ( NULL != mOffsetsMap )
755    {
756        delete [] mOffsetsMap;
757        mOffsetsMap = NULL;
758    }
759
760    if( mFD != -1)
761    {
762        close(mFD);  // close duped handle
763        mFD = -1;
764    }
765
766    return NO_ERROR;
767}
768
769
770bool ANativeWindowDisplayAdapter::supportsExternalBuffering()
771{
772    return false;
773}
774
775int ANativeWindowDisplayAdapter::useBuffers(void *bufArr, int num)
776{
777    return NO_ERROR;
778}
779
780void ANativeWindowDisplayAdapter::displayThread()
781{
782    bool shouldLive = true;
783    int timeout = 0;
784    status_t ret;
785
786    LOG_FUNCTION_NAME;
787
788    while(shouldLive)
789        {
790        ret = TIUTILS::MessageQueue::waitForMsg(&mDisplayThread->msgQ()
791                                                                ,  &mDisplayQ
792                                                                , NULL
793                                                                , ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT);
794
795        if ( !mDisplayThread->msgQ().isEmpty() )
796            {
797            ///Received a message from CameraHal, process it
798            shouldLive = processHalMsg();
799
800            }
801        else  if( !mDisplayQ.isEmpty())
802            {
803            if ( mDisplayState== ANativeWindowDisplayAdapter::DISPLAY_INIT )
804                {
805
806                ///If display adapter is not started, continue
807                continue;
808
809                }
810            else
811                {
812                TIUTILS::Message msg;
813                ///Get the dummy msg from the displayQ
814                if(mDisplayQ.get(&msg)!=NO_ERROR)
815                    {
816                    CAMHAL_LOGEA("Error in getting message from display Q");
817                    continue;
818                }
819
820                // There is a frame from ANativeWindow for us to dequeue
821                // We dequeue and return the frame back to Camera adapter
822                if(mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED)
823                {
824                    handleFrameReturn();
825                }
826
827                if (mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_EXITED)
828                    {
829                    ///we exit the thread even though there are frames still to dequeue. They will be dequeued
830                    ///in disableDisplay
831                    shouldLive = false;
832                }
833            }
834        }
835    }
836
837    LOG_FUNCTION_NAME_EXIT;
838}
839
840
841bool ANativeWindowDisplayAdapter::processHalMsg()
842{
843    TIUTILS::Message msg;
844
845    LOG_FUNCTION_NAME;
846
847
848    mDisplayThread->msgQ().get(&msg);
849    bool ret = true, invalidCommand = false;
850
851    switch ( msg.command )
852        {
853
854        case DisplayThread::DISPLAY_START:
855
856            CAMHAL_LOGDA("Display thread received DISPLAY_START command from Camera HAL");
857            mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STARTED;
858
859            break;
860
861        case DisplayThread::DISPLAY_STOP:
862
863            ///@bug There is no API to disable SF without destroying it
864            ///@bug Buffers might still be w/ display and will get displayed
865            ///@remarks Ideal seqyence should be something like this
866            ///mOverlay->setParameter("enabled", false);
867            CAMHAL_LOGDA("Display thread received DISPLAY_STOP command from Camera HAL");
868            mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STOPPED;
869
870            break;
871
872        case DisplayThread::DISPLAY_EXIT:
873
874            CAMHAL_LOGDA("Display thread received DISPLAY_EXIT command from Camera HAL.");
875            CAMHAL_LOGDA("Stopping display thread...");
876            mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_EXITED;
877            ///Note that the SF can have pending buffers when we disable the display
878            ///This is normal and the expectation is that they may not be displayed.
879            ///This is to ensure that the user experience is not impacted
880            ret = false;
881            break;
882
883        default:
884
885            CAMHAL_LOGEB("Invalid Display Thread Command 0x%x.", msg.command);
886            invalidCommand = true;
887
888            break;
889    }
890
891    ///Signal the semaphore if it is sent as part of the message
892    if ( ( msg.arg1 ) && ( !invalidCommand ) )
893        {
894
895        CAMHAL_LOGDA("+Signalling display semaphore");
896        Semaphore &sem = *((Semaphore*)msg.arg1);
897
898        sem.Signal();
899
900        CAMHAL_LOGDA("-Signalling display semaphore");
901    }
902
903
904    LOG_FUNCTION_NAME_EXIT;
905    return ret;
906}
907
908
909status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame)
910{
911    status_t ret = NO_ERROR;
912    uint32_t actualFramesWithDisplay = 0;
913    android_native_buffer_t *buffer = NULL;
914    int i;
915
916    ///@todo Do cropping based on the stabilized frame coordinates
917    ///@todo Insert logic to drop frames here based on refresh rate of
918    ///display or rendering rate whichever is lower
919    ///Queue the buffer to overlay
920    for ( i = 0; i < mBufferCount; i++ )
921        {
922        if ( ((int) dispFrame.mBuffer ) == (int)mGrallocHandleMap[i] )
923            {
924            break;
925        }
926    }
927
928    if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED &&
929                (!mPaused ||  CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) &&
930                !mSuspend)
931    {
932        Mutex::Autolock lock(mLock);
933        uint32_t xOff = (dispFrame.mOffset% PAGE_SIZE);
934        uint32_t yOff = (dispFrame.mOffset / PAGE_SIZE);
935
936        // Set crop only if current x and y offsets do not match with frame offsets
937        if((mXOff!=xOff) || (mYOff!=yOff))
938        {
939            CAMHAL_LOGDB("Offset %d xOff = %d, yOff = %d", dispFrame.mOffset, xOff, yOff);
940            uint8_t bytesPerPixel;
941            ///Calculate bytes per pixel based on the pixel format
942            if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
943                {
944                bytesPerPixel = 2;
945                }
946            else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0)
947                {
948                bytesPerPixel = 2;
949                }
950            else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0)
951                {
952                bytesPerPixel = 1;
953                }
954            else
955                {
956                bytesPerPixel = 1;
957            }
958
959            CAMHAL_LOGVB(" crop.left = %d crop.top = %d crop.right = %d crop.bottom = %d",
960                          xOff/bytesPerPixel, yOff , (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight);
961            // We'll ignore any errors here, if the surface is
962            // already invalid, we'll know soon enough.
963            mANativeWindow->set_crop(mANativeWindow, xOff/bytesPerPixel, yOff,
964                                     (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight);
965
966            ///Update the current x and y offsets
967            mXOff = xOff;
968            mYOff = yOff;
969        }
970
971        ret = mANativeWindow->enqueue_buffer(mANativeWindow, mBufferHandleMap[i]);
972        if (ret != 0) {
973            LOGE("Surface::queueBuffer returned error %d", ret);
974        }
975
976        mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer);
977
978
979        // HWComposer has not minimum buffer requirement. We should be able to dequeue
980        // the buffer immediately
981        TIUTILS::Message msg;
982        mDisplayQ.put(&msg);
983
984
985#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
986
987        if ( mMeasureStandby )
988            {
989            CameraHal::PPM("Standby to first shot: Sensor Change completed - ", &mStandbyToShot);
990            mMeasureStandby = false;
991            }
992        else if (CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType)
993            {
994            CameraHal::PPM("Shot to snapshot: ", &mStartCapture);
995            mShotToShot = true;
996            }
997        else if ( mShotToShot )
998            {
999            CameraHal::PPM("Shot to shot: ", &mStartCapture);
1000            mShotToShot = false;
1001        }
1002#endif
1003
1004    }
1005    else
1006    {
1007        Mutex::Autolock lock(mLock);
1008        // cancel buffer and dequeue another one
1009        ret = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]);
1010        if (ret != 0) {
1011            LOGE("Surface::queueBuffer returned error %d", ret);
1012        }
1013
1014        mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer);
1015
1016        TIUTILS::Message msg;
1017        mDisplayQ.put(&msg);
1018        ret = NO_ERROR;
1019    }
1020
1021    return ret;
1022}
1023
1024
1025bool ANativeWindowDisplayAdapter::handleFrameReturn()
1026{
1027    status_t err;
1028    buffer_handle_t* buf;
1029    int i = 0;
1030    int stride;  // dummy variable to get stride
1031    // TODO(XXX): Do we need to keep stride information in camera hal?
1032
1033    err = mANativeWindow->dequeue_buffer(mANativeWindow, &buf, &stride);
1034    if (err != 0) {
1035        CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1036    }
1037
1038    err = mANativeWindow->lock_buffer(mANativeWindow, buf);
1039    if (err != 0) {
1040        CAMHAL_LOGEB("lockbuffer failed: %s (%d)", strerror(-err), -err);
1041    }
1042
1043    for(i = 0; i < mBufferCount; i++)
1044    {
1045        if (mBufferHandleMap[i] == buf)
1046            break;
1047    }
1048
1049    mFramesWithCameraAdapterMap.add((int) mGrallocHandleMap[i], i);
1050
1051    CAMHAL_LOGVB("handleFrameReturn: found graphic buffer %d of %d", i, mBufferCount-1);
1052    mFrameProvider->returnFrame( (void*)mGrallocHandleMap[i], CameraFrame::PREVIEW_FRAME_SYNC);
1053    return true;
1054}
1055
1056void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame)
1057{
1058
1059    if ( NULL != caFrame )
1060        {
1061        if ( NULL != caFrame->mCookie )
1062            {
1063            ANativeWindowDisplayAdapter *da = (ANativeWindowDisplayAdapter*) caFrame->mCookie;
1064            da->frameCallback(caFrame);
1065        }
1066        else
1067            {
1068            CAMHAL_LOGEB("Invalid Cookie in Camera Frame = %p, Cookie = %p", caFrame, caFrame->mCookie);
1069            }
1070        }
1071    else
1072        {
1073        CAMHAL_LOGEB("Invalid Camera Frame = %p", caFrame);
1074    }
1075
1076}
1077
1078void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame)
1079{
1080    ///Call queueBuffer of overlay in the context of the callback thread
1081    DisplayFrame df;
1082    df.mBuffer = caFrame->mBuffer;
1083    df.mType = (CameraFrame::FrameType) caFrame->mFrameType;
1084    df.mOffset = caFrame->mOffset;
1085    df.mWidthStride = caFrame->mAlignment;
1086    df.mLength = caFrame->mLength;
1087    df.mWidth = caFrame->mWidth;
1088    df.mHeight = caFrame->mHeight;
1089    PostFrame(df);
1090}
1091
1092
1093/*--------------------ANativeWindowDisplayAdapter Class ENDS here-----------------------------*/
1094
1095};
1096
1097