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