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