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 | |
26 | namespace android { |
27 | |
28 | ///Constant declarations |
29 | ///@todo Check the time units |
30 | const int ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT = 1000; // seconds |
31 | |
32 | //Suspends buffers after given amount of failed dq's |
33 | const int ANativeWindowDisplayAdapter::FAILED_DQS_TO_SUSPEND = 3; |
34 | |
35 | |
36 | const 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 | |
75 | static 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 | */ |
110 | ANativeWindowDisplayAdapter::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 | |
156 | ANativeWindowDisplayAdapter::~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 | |
201 | status_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 | |
228 | int 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 | |
250 | int 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 | |
276 | int 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 | |
300 | status_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 | |
320 | int 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 | |
379 | int 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 | |
450 | status_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 | |
467 | void 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 |
484 | void* 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 | |
682 | uint32_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 | |
735 | int 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 | |
772 | int 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 | |
791 | status_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 | |
827 | int 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 | |
875 | bool ANativeWindowDisplayAdapter::supportsExternalBuffering() |
876 | { |
877 | return false; |
878 | } |
879 | |
880 | int ANativeWindowDisplayAdapter::useBuffers(void *bufArr, int num) |
881 | { |
882 | return NO_ERROR; |
883 | } |
884 | |
885 | void 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 | |
945 | bool 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 | |
998 | status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame) |
999 | { |
1000 | status_t ret = NO_ERROR; |
1001 | uint32_t actualFramesWithDisplay = 0; |
1002 | android_native_buffer_t *buffer = NULL; |
1003 | 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 | |
1128 | bool 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 | |
1200 | void 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 | |
1221 | void 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 |