camera2_utils.cpp revision 567b4a24fa9fedf0086af5e0bb8e45bd3294bc9d
1/* 2 * Copyright (C) 2012 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// Utility classes for camera2 HAL testing 18 19#define LOG_TAG "Camera2_test_utils" 20#define LOG_NDEBUG 0 21 22#include "utils/Log.h" 23#include "camera2_utils.h" 24 25namespace android { 26 27/** 28 * MetadataQueue 29 */ 30 31MetadataQueue::MetadataQueue(): 32 mDevice(NULL), 33 mFrameCount(0), 34 mCount(0), 35 mStreamSlotCount(0), 36 mSignalConsumer(true) 37{ 38 camera2_request_queue_src_ops::dequeue_request = consumer_dequeue; 39 camera2_request_queue_src_ops::request_count = consumer_buffer_count; 40 camera2_request_queue_src_ops::free_request = consumer_free; 41 42 camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue; 43 camera2_frame_queue_dst_ops::cancel_frame = producer_cancel; 44 camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue; 45} 46 47MetadataQueue::~MetadataQueue() { 48 freeBuffers(mEntries.begin(), mEntries.end()); 49 freeBuffers(mStreamSlot.begin(), mStreamSlot.end()); 50} 51 52// Interface to camera2 HAL as consumer (input requests/reprocessing) 53camera2_request_queue_src_ops_t* MetadataQueue::getToConsumerInterface() { 54 return static_cast<camera2_request_queue_src_ops_t*>(this); 55} 56 57void MetadataQueue::setFromConsumerInterface(camera2_device_t *d) { 58 mDevice = d; 59} 60 61camera2_frame_queue_dst_ops_t* MetadataQueue::getToProducerInterface() { 62 return static_cast<camera2_frame_queue_dst_ops_t*>(this); 63} 64 65// Real interfaces 66status_t MetadataQueue::enqueue(camera_metadata_t *buf) { 67 Mutex::Autolock l(mMutex); 68 69 mCount++; 70 mEntries.push_back(buf); 71 notEmpty.signal(); 72 73 if (mSignalConsumer && mDevice != NULL) { 74 mSignalConsumer = false; 75 76 mMutex.unlock(); 77 ALOGV("%s: Signaling consumer", __FUNCTION__); 78 mDevice->ops->notify_request_queue_not_empty(mDevice); 79 mMutex.lock(); 80 } 81 return OK; 82} 83 84int MetadataQueue::getBufferCount() { 85 Mutex::Autolock l(mMutex); 86 if (mStreamSlotCount > 0) { 87 return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS; 88 } 89 return mCount; 90} 91 92status_t MetadataQueue::dequeue(camera_metadata_t **buf, bool incrementCount) { 93 Mutex::Autolock l(mMutex); 94 95 if (mCount == 0) { 96 if (mStreamSlotCount == 0) { 97 ALOGV("%s: Empty", __FUNCTION__); 98 *buf = NULL; 99 mSignalConsumer = true; 100 return OK; 101 } 102 ALOGV("%s: Streaming %d frames to queue", __FUNCTION__, 103 mStreamSlotCount); 104 105 for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin(); 106 slotEntry != mStreamSlot.end(); 107 slotEntry++ ) { 108 size_t entries = get_camera_metadata_entry_count(*slotEntry); 109 size_t dataBytes = get_camera_metadata_data_count(*slotEntry); 110 111 camera_metadata_t *copy = allocate_camera_metadata(entries, dataBytes); 112 append_camera_metadata(copy, *slotEntry); 113 mEntries.push_back(copy); 114 } 115 mCount = mStreamSlotCount; 116 } 117 ALOGV("MetadataQueue: deque (%d buffers)", mCount); 118 camera_metadata_t *b = *(mEntries.begin()); 119 mEntries.erase(mEntries.begin()); 120 121 if (incrementCount) { 122 add_camera_metadata_entry(b, 123 ANDROID_REQUEST_FRAME_COUNT, 124 (void**)&mFrameCount, 1); 125 mFrameCount++; 126 } 127 128 *buf = b; 129 mCount--; 130 131 return OK; 132} 133 134status_t MetadataQueue::waitForBuffer(nsecs_t timeout) { 135 Mutex::Autolock l(mMutex); 136 status_t res; 137 while (mCount == 0) { 138 res = notEmpty.waitRelative(mMutex,timeout); 139 if (res != OK) return res; 140 } 141 return OK; 142} 143 144status_t MetadataQueue::setStreamSlot(camera_metadata_t *buf) { 145 if (buf == NULL) { 146 freeBuffers(mStreamSlot.begin(), mStreamSlot.end()); 147 mStreamSlotCount = 0; 148 return OK; 149 } 150 if (mStreamSlotCount > 1) { 151 List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin(); 152 freeBuffers(++mStreamSlot.begin(), mStreamSlot.end()); 153 mStreamSlotCount = 1; 154 } 155 if (mStreamSlotCount == 1) { 156 free_camera_metadata( *(mStreamSlot.begin()) ); 157 *(mStreamSlot.begin()) = buf; 158 } else { 159 mStreamSlot.push_front(buf); 160 mStreamSlotCount = 1; 161 } 162 return OK; 163} 164 165status_t MetadataQueue::setStreamSlot(const List<camera_metadata_t*> &bufs) { 166 if (mStreamSlotCount > 0) { 167 freeBuffers(mStreamSlot.begin(), mStreamSlot.end()); 168 } 169 mStreamSlot = bufs; 170 mStreamSlotCount = mStreamSlot.size(); 171 172 return OK; 173} 174 175status_t MetadataQueue::freeBuffers(List<camera_metadata_t*>::iterator start, 176 List<camera_metadata_t*>::iterator end) { 177 while (start != end) { 178 free_camera_metadata(*start); 179 start = mStreamSlot.erase(start); 180 } 181 return OK; 182} 183 184int MetadataQueue::consumer_buffer_count( 185 camera2_request_queue_src_ops_t *q) { 186 MetadataQueue *queue = static_cast<MetadataQueue *>(q); 187 return queue->getBufferCount(); 188} 189 190int MetadataQueue::consumer_dequeue(camera2_request_queue_src_ops_t *q, 191 camera_metadata_t **buffer) { 192 MetadataQueue *queue = static_cast<MetadataQueue *>(q); 193 return queue->dequeue(buffer, true); 194} 195 196int MetadataQueue::consumer_free(camera2_request_queue_src_ops_t *q, 197 camera_metadata_t *old_buffer) { 198 MetadataQueue *queue = static_cast<MetadataQueue *>(q); 199 free_camera_metadata(old_buffer); 200 return OK; 201} 202 203int MetadataQueue::producer_dequeue(camera2_frame_queue_dst_ops_t *q, 204 size_t entries, size_t bytes, 205 camera_metadata_t **buffer) { 206 camera_metadata_t *new_buffer = 207 allocate_camera_metadata(entries, bytes); 208 if (new_buffer == NULL) return NO_MEMORY; 209 *buffer = new_buffer; 210 return OK; 211} 212 213int MetadataQueue::producer_cancel(camera2_frame_queue_dst_ops_t *q, 214 camera_metadata_t *old_buffer) { 215 free_camera_metadata(old_buffer); 216 return OK; 217} 218 219int MetadataQueue::producer_enqueue(camera2_frame_queue_dst_ops_t *q, 220 camera_metadata_t *filled_buffer) { 221 MetadataQueue *queue = static_cast<MetadataQueue *>(q); 222 return queue->enqueue(filled_buffer); 223} 224 225/** 226 * NotifierListener 227 */ 228 229NotifierListener::NotifierListener() { 230} 231 232status_t NotifierListener::getNotificationsFrom(camera2_device *dev) { 233 if (!dev) return BAD_VALUE; 234 status_t err; 235 err = dev->ops->set_notify_callback(dev, 236 notify_callback_dispatch, 237 (void*)this); 238 return err; 239} 240 241status_t NotifierListener::getNextNotification(int32_t *msg_type, 242 int32_t *ext1, 243 int32_t *ext2, 244 int32_t *ext3) { 245 Mutex::Autolock l(mMutex); 246 if (mNotifications.size() == 0) return BAD_VALUE; 247 return getNextNotificationLocked(msg_type, ext1, ext2, ext3); 248} 249 250status_t NotifierListener::waitForNotification(int32_t *msg_type, 251 int32_t *ext1, 252 int32_t *ext2, 253 int32_t *ext3) { 254 Mutex::Autolock l(mMutex); 255 while (mNotifications.size() == 0) { 256 mNewNotification.wait(mMutex); 257 } 258 return getNextNotificationLocked(msg_type, ext1, ext2, ext3); 259} 260 261int NotifierListener::numNotifications() { 262 Mutex::Autolock l(mMutex); 263 return mNotifications.size(); 264} 265 266status_t NotifierListener::getNextNotificationLocked(int32_t *msg_type, 267 int32_t *ext1, 268 int32_t *ext2, 269 int32_t *ext3) { 270 *msg_type = mNotifications.begin()->msg_type; 271 *ext1 = mNotifications.begin()->ext1; 272 *ext2 = mNotifications.begin()->ext2; 273 *ext3 = mNotifications.begin()->ext3; 274 mNotifications.erase(mNotifications.begin()); 275 return OK; 276} 277 278void NotifierListener::onNotify(int32_t msg_type, 279 int32_t ext1, 280 int32_t ext2, 281 int32_t ext3) { 282 Mutex::Autolock l(mMutex); 283 mNotifications.push_back(Notification(msg_type, ext1, ext2, ext3)); 284 mNewNotification.signal(); 285} 286 287void NotifierListener::notify_callback_dispatch(int32_t msg_type, 288 int32_t ext1, 289 int32_t ext2, 290 int32_t ext3, 291 void *user) { 292 NotifierListener *me = reinterpret_cast<NotifierListener*>(user); 293 me->onNotify(msg_type, ext1, ext2, ext3); 294} 295 296/** 297 * StreamAdapter 298 */ 299 300#ifndef container_of 301#define container_of(ptr, type, member) \ 302 (type *)((char*)(ptr) - offsetof(type, member)) 303#endif 304 305StreamAdapter::StreamAdapter(sp<ISurfaceTexture> consumer): 306 mState(UNINITIALIZED), mDevice(NULL), 307 mId(-1), 308 mWidth(0), mHeight(0), mFormatRequested(0) 309{ 310 mConsumerInterface = new SurfaceTextureClient(consumer); 311 camera2_stream_ops::dequeue_buffer = dequeue_buffer; 312 camera2_stream_ops::enqueue_buffer = enqueue_buffer; 313 camera2_stream_ops::cancel_buffer = cancel_buffer; 314 camera2_stream_ops::set_crop = set_crop; 315} 316 317StreamAdapter::~StreamAdapter() { 318 disconnect(); 319} 320 321status_t StreamAdapter::connectToDevice(camera2_device_t *d, 322 uint32_t width, uint32_t height, int format) { 323 if (mState != UNINITIALIZED) return INVALID_OPERATION; 324 if (d == NULL) { 325 ALOGE("%s: Null device passed to stream adapter", __FUNCTION__); 326 return BAD_VALUE; 327 } 328 329 status_t res; 330 331 mWidth = width; 332 mHeight = height; 333 mFormatRequested = format; 334 335 // Allocate device-side stream interface 336 337 uint32_t id; 338 uint32_t formatActual; 339 uint32_t usage; 340 uint32_t maxBuffers = 2; 341 res = d->ops->allocate_stream(d, 342 mWidth, mHeight, mFormatRequested, getStreamOps(), 343 &id, &formatActual, &usage, &maxBuffers); 344 if (res != OK) { 345 ALOGE("%s: Device stream allocation failed: %s (%d)", 346 __FUNCTION__, strerror(-res), res); 347 mState = UNINITIALIZED; 348 return res; 349 } 350 mDevice = d; 351 352 mId = id; 353 mFormat = formatActual; 354 mUsage = usage; 355 mMaxProducerBuffers = maxBuffers; 356 357 // Configure consumer-side ANativeWindow interface 358 359 res = native_window_api_connect(mConsumerInterface.get(), 360 NATIVE_WINDOW_API_CAMERA); 361 if (res != OK) { 362 ALOGE("%s: Unable to connect to native window for stream %d", 363 __FUNCTION__, mId); 364 mState = ALLOCATED; 365 return res; 366 } 367 368 res = native_window_set_usage(mConsumerInterface.get(), mUsage); 369 if (res != OK) { 370 ALOGE("%s: Unable to configure usage %08x for stream %d", 371 __FUNCTION__, mUsage, mId); 372 mState = CONNECTED; 373 return res; 374 } 375 376 res = native_window_set_buffers_geometry(mConsumerInterface.get(), 377 mWidth, mHeight, mFormat); 378 if (res != OK) { 379 ALOGE("%s: Unable to configure buffer geometry" 380 " %d x %d, format 0x%x for stream %d", 381 __FUNCTION__, mWidth, mHeight, mFormat, mId); 382 mState = CONNECTED; 383 return res; 384 } 385 386 int maxConsumerBuffers; 387 res = mConsumerInterface->query(mConsumerInterface.get(), 388 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers); 389 if (res != OK) { 390 ALOGE("%s: Unable to query consumer undequeued" 391 " buffer count for stream %d", __FUNCTION__, mId); 392 mState = CONNECTED; 393 return res; 394 } 395 mMaxConsumerBuffers = maxConsumerBuffers; 396 397 ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__, 398 mMaxProducerBuffers, mMaxConsumerBuffers); 399 400 int totalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers; 401 402 res = native_window_set_buffer_count(mConsumerInterface.get(), 403 totalBuffers); 404 if (res != OK) { 405 ALOGE("%s: Unable to set buffer count for stream %d", 406 __FUNCTION__, mId); 407 mState = CONNECTED; 408 return res; 409 } 410 411 // Register allocated buffers with HAL device 412 buffer_handle_t *buffers = new buffer_handle_t[totalBuffers]; 413 ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[totalBuffers]; 414 int bufferIdx = 0; 415 for (; bufferIdx < totalBuffers; bufferIdx++) { 416 res = mConsumerInterface->dequeueBuffer(mConsumerInterface.get(), 417 &anwBuffers[bufferIdx]); 418 if (res != OK) { 419 ALOGE("%s: Unable to dequeue buffer %d for initial registration for" 420 "stream %d", __FUNCTION__, bufferIdx, mId); 421 mState = CONNECTED; 422 goto cleanUpBuffers; 423 } 424 425 res = mConsumerInterface->lockBuffer(mConsumerInterface.get(), 426 anwBuffers[bufferIdx]); 427 if (res != OK) { 428 ALOGE("%s: Unable to lock buffer %d for initial registration for" 429 "stream %d", __FUNCTION__, bufferIdx, mId); 430 mState = CONNECTED; 431 bufferIdx++; 432 goto cleanUpBuffers; 433 } 434 435 buffers[bufferIdx] = anwBuffers[bufferIdx]->handle; 436 } 437 438 res = mDevice->ops->register_stream_buffers(mDevice, 439 mId, 440 totalBuffers, 441 buffers); 442 if (res != OK) { 443 ALOGE("%s: Unable to register buffers with HAL device for stream %d", 444 __FUNCTION__, mId); 445 mState = CONNECTED; 446 } else { 447 mState = ACTIVE; 448 } 449 450cleanUpBuffers: 451 for (int i = 0; i < bufferIdx; i++) { 452 res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(), 453 anwBuffers[i]); 454 } 455 delete anwBuffers; 456 delete buffers; 457 458 return res; 459} 460 461status_t StreamAdapter::disconnect() { 462 status_t res; 463 if (mState >= ALLOCATED) { 464 res = mDevice->ops->release_stream(mDevice, mId); 465 if (res != OK) { 466 ALOGE("%s: Unable to release stream %d", 467 __FUNCTION__, mId); 468 return res; 469 } 470 } 471 if (mState >= CONNECTED) { 472 res = native_window_api_disconnect(mConsumerInterface.get(), 473 NATIVE_WINDOW_API_CAMERA); 474 if (res != OK) { 475 ALOGE("%s: Unable to disconnect stream %d from native window", 476 __FUNCTION__, mId); 477 return res; 478 } 479 } 480 mId = -1; 481 mState = DISCONNECTED; 482 return OK; 483} 484 485int StreamAdapter::getId() { 486 return mId; 487} 488 489camera2_stream_ops *StreamAdapter::getStreamOps() { 490 return static_cast<camera2_stream_ops *>(this); 491} 492 493ANativeWindow* StreamAdapter::toANW(camera2_stream_ops_t *w) { 494 return static_cast<StreamAdapter*>(w)->mConsumerInterface.get(); 495} 496 497int StreamAdapter::dequeue_buffer(camera2_stream_ops_t *w, 498 buffer_handle_t** buffer) { 499 int res; 500 int state = static_cast<StreamAdapter*>(w)->mState; 501 if (state != ACTIVE) { 502 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); 503 return INVALID_OPERATION; 504 } 505 506 ANativeWindow *a = toANW(w); 507 ANativeWindowBuffer* anb; 508 res = a->dequeueBuffer(a, &anb); 509 if (res != OK) return res; 510 res = a->lockBuffer(a, anb); 511 if (res != OK) return res; 512 513 *buffer = &(anb->handle); 514 515 return res; 516} 517 518int StreamAdapter::enqueue_buffer(camera2_stream_ops_t* w, 519 int64_t timestamp, 520 buffer_handle_t* buffer) { 521 int state = static_cast<StreamAdapter*>(w)->mState; 522 if (state != ACTIVE) { 523 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); 524 return INVALID_OPERATION; 525 } 526 ANativeWindow *a = toANW(w); 527 status_t err; 528 err = native_window_set_buffers_timestamp(a, timestamp); 529 if (err != OK) return err; 530 return a->queueBuffer(a, 531 container_of(buffer, ANativeWindowBuffer, handle)); 532} 533 534int StreamAdapter::cancel_buffer(camera2_stream_ops_t* w, 535 buffer_handle_t* buffer) { 536 int state = static_cast<StreamAdapter*>(w)->mState; 537 if (state != ACTIVE) { 538 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); 539 return INVALID_OPERATION; 540 } 541 ANativeWindow *a = toANW(w); 542 return a->cancelBuffer(a, 543 container_of(buffer, ANativeWindowBuffer, handle)); 544} 545 546int StreamAdapter::set_crop(camera2_stream_ops_t* w, 547 int left, int top, int right, int bottom) { 548 int state = static_cast<StreamAdapter*>(w)->mState; 549 if (state != ACTIVE) { 550 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); 551 return INVALID_OPERATION; 552 } 553 ANativeWindow *a = toANW(w); 554 android_native_rect_t crop = { left, top, right, bottom }; 555 return native_window_set_crop(a, &crop); 556} 557 558/** 559 * FrameWaiter 560 */ 561 562FrameWaiter::FrameWaiter(): 563 mPendingFrames(0) { 564} 565 566status_t FrameWaiter::waitForFrame(nsecs_t timeout) { 567 status_t res; 568 Mutex::Autolock lock(mMutex); 569 while (mPendingFrames == 0) { 570 res = mCondition.waitRelative(mMutex, timeout); 571 if (res != OK) return res; 572 } 573 mPendingFrames--; 574 return OK; 575} 576 577void FrameWaiter::onFrameAvailable() { 578 Mutex::Autolock lock(mMutex); 579 mPendingFrames++; 580 mCondition.signal(); 581} 582 583} // namespace android 584