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