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