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