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