• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
28 namespace android {
29 
30 ///Constant declarations
31 ///@todo Check the time units
32 const int ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT = 1000;  // seconds
33 
34 //Suspends buffers after given amount of failed dq's
35 const int ANativeWindowDisplayAdapter::FAILED_DQS_TO_SUSPEND = 3;
36 
37 
toOMXPixFormat(const char * parameters_format)38 OMX_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 
getPixFormatConstant(const char * parameters_format)73 const 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 
getBufSize(const char * parameters_format,int width,int height)111 const 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  */
ANativeWindowDisplayAdapter()144 ANativeWindowDisplayAdapter::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 
~ANativeWindowDisplayAdapter()189 ANativeWindowDisplayAdapter::~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 
initialize()234 status_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 
setPreviewWindow(preview_stream_ops_t * window)261 int 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 
setFrameProvider(FrameNotifier * frameProvider)287 int 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 
setErrorHandler(ErrorNotifier * errorNotifier)313 int 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 
setSnapshotTimeRef(struct timeval * refTime)337 status_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 
enableDisplay(int width,int height,struct timeval * refTime,S3DParameters * s3dParams)357 int 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 
disableDisplay(bool cancel_buffer)416 int 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 
pauseDisplay(bool pause)489 status_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 
destroy()506 void 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
allocateBuffer(int width,int height,const char * format,int & bytes,int numBufs)523 void* 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 
getOffsets()700 uint32_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 
maxQueueableBuffers(unsigned int & queueable)752 int 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 
getFd()789 int 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 
returnBuffersToWindow()807 status_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 
freeBuffer(void * buf)842 int 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 
supportsExternalBuffering()890 bool ANativeWindowDisplayAdapter::supportsExternalBuffering()
891 {
892     return false;
893 }
894 
useBuffers(void * bufArr,int num)895 int ANativeWindowDisplayAdapter::useBuffers(void *bufArr, int num)
896 {
897     return NO_ERROR;
898 }
899 
displayThread()900 void 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 
processHalMsg()961 bool 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 
PostFrame(ANativeWindowDisplayAdapter::DisplayFrame & dispFrame)1029 status_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 
handleFrameReturn()1158 bool 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 
frameCallbackRelay(CameraFrame * caFrame)1229 void 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 
frameCallback(CameraFrame * caFrame)1251 void 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