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