camera2_utils.cpp revision 2388a2dc91979364d96e49456b189f904f0267f3
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) 53const camera2_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 61const camera2_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 184MetadataQueue* MetadataQueue::getInstance( 185 const camera2_request_queue_src_ops_t *q) { 186 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q); 187 return const_cast<MetadataQueue*>(cmq); 188} 189 190MetadataQueue* MetadataQueue::getInstance( 191 const camera2_frame_queue_dst_ops_t *q) { 192 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q); 193 return const_cast<MetadataQueue*>(cmq); 194} 195 196int MetadataQueue::consumer_buffer_count( 197 const camera2_request_queue_src_ops_t *q) { 198 MetadataQueue *queue = getInstance(q); 199 return queue->getBufferCount(); 200} 201 202int MetadataQueue::consumer_dequeue(const camera2_request_queue_src_ops_t *q, 203 camera_metadata_t **buffer) { 204 MetadataQueue *queue = getInstance(q); 205 return queue->dequeue(buffer, true); 206} 207 208int MetadataQueue::consumer_free(const camera2_request_queue_src_ops_t *q, 209 camera_metadata_t *old_buffer) { 210 MetadataQueue *queue = getInstance(q); 211 free_camera_metadata(old_buffer); 212 return OK; 213} 214 215int MetadataQueue::producer_dequeue(const camera2_frame_queue_dst_ops_t *q, 216 size_t entries, size_t bytes, 217 camera_metadata_t **buffer) { 218 camera_metadata_t *new_buffer = 219 allocate_camera_metadata(entries, bytes); 220 if (new_buffer == NULL) return NO_MEMORY; 221 *buffer = new_buffer; 222 return OK; 223} 224 225int MetadataQueue::producer_cancel(const camera2_frame_queue_dst_ops_t *q, 226 camera_metadata_t *old_buffer) { 227 free_camera_metadata(old_buffer); 228 return OK; 229} 230 231int MetadataQueue::producer_enqueue(const camera2_frame_queue_dst_ops_t *q, 232 camera_metadata_t *filled_buffer) { 233 MetadataQueue *queue = getInstance(q); 234 return queue->enqueue(filled_buffer); 235} 236 237/** 238 * NotifierListener 239 */ 240 241NotifierListener::NotifierListener() { 242} 243 244status_t NotifierListener::getNotificationsFrom(camera2_device *dev) { 245 if (!dev) return BAD_VALUE; 246 status_t err; 247 err = dev->ops->set_notify_callback(dev, 248 notify_callback_dispatch, 249 (void*)this); 250 return err; 251} 252 253status_t NotifierListener::getNextNotification(int32_t *msg_type, 254 int32_t *ext1, 255 int32_t *ext2, 256 int32_t *ext3) { 257 Mutex::Autolock l(mMutex); 258 if (mNotifications.size() == 0) return BAD_VALUE; 259 return getNextNotificationLocked(msg_type, ext1, ext2, ext3); 260} 261 262status_t NotifierListener::waitForNotification(int32_t *msg_type, 263 int32_t *ext1, 264 int32_t *ext2, 265 int32_t *ext3) { 266 Mutex::Autolock l(mMutex); 267 while (mNotifications.size() == 0) { 268 mNewNotification.wait(mMutex); 269 } 270 return getNextNotificationLocked(msg_type, ext1, ext2, ext3); 271} 272 273int NotifierListener::numNotifications() { 274 Mutex::Autolock l(mMutex); 275 return mNotifications.size(); 276} 277 278status_t NotifierListener::getNextNotificationLocked(int32_t *msg_type, 279 int32_t *ext1, 280 int32_t *ext2, 281 int32_t *ext3) { 282 *msg_type = mNotifications.begin()->msg_type; 283 *ext1 = mNotifications.begin()->ext1; 284 *ext2 = mNotifications.begin()->ext2; 285 *ext3 = mNotifications.begin()->ext3; 286 mNotifications.erase(mNotifications.begin()); 287 return OK; 288} 289 290void NotifierListener::onNotify(int32_t msg_type, 291 int32_t ext1, 292 int32_t ext2, 293 int32_t ext3) { 294 Mutex::Autolock l(mMutex); 295 mNotifications.push_back(Notification(msg_type, ext1, ext2, ext3)); 296 mNewNotification.signal(); 297} 298 299void NotifierListener::notify_callback_dispatch(int32_t msg_type, 300 int32_t ext1, 301 int32_t ext2, 302 int32_t ext3, 303 void *user) { 304 NotifierListener *me = reinterpret_cast<NotifierListener*>(user); 305 me->onNotify(msg_type, ext1, ext2, ext3); 306} 307 308/** 309 * StreamAdapter 310 */ 311 312#ifndef container_of 313#define container_of(ptr, type, member) \ 314 (type *)((char*)(ptr) - offsetof(type, member)) 315#endif 316 317StreamAdapter::StreamAdapter(sp<ISurfaceTexture> consumer): 318 mState(UNINITIALIZED), mDevice(NULL), 319 mId(-1), 320 mWidth(0), mHeight(0), mFormat(0) 321{ 322 mConsumerInterface = new SurfaceTextureClient(consumer); 323 camera2_stream_ops::dequeue_buffer = dequeue_buffer; 324 camera2_stream_ops::enqueue_buffer = enqueue_buffer; 325 camera2_stream_ops::cancel_buffer = cancel_buffer; 326 camera2_stream_ops::set_crop = set_crop; 327} 328 329StreamAdapter::~StreamAdapter() { 330 disconnect(); 331} 332 333status_t StreamAdapter::connectToDevice(camera2_device_t *d, 334 uint32_t width, uint32_t height, int format) { 335 if (mState != UNINITIALIZED) return INVALID_OPERATION; 336 if (d == NULL) { 337 ALOGE("%s: Null device passed to stream adapter", __FUNCTION__); 338 return BAD_VALUE; 339 } 340 341 status_t res; 342 343 mWidth = width; 344 mHeight = height; 345 mFormat = format; 346 347 // Allocate device-side stream interface 348 349 uint32_t id; 350 uint32_t formatActual; // ignored 351 uint32_t usage; 352 uint32_t maxBuffers = 2; 353 res = d->ops->allocate_stream(d, 354 mWidth, mHeight, mFormat, getStreamOps(), 355 &id, &formatActual, &usage, &maxBuffers); 356 if (res != OK) { 357 ALOGE("%s: Device stream allocation failed: %s (%d)", 358 __FUNCTION__, strerror(-res), res); 359 mState = UNINITIALIZED; 360 return res; 361 } 362 mDevice = d; 363 364 mId = id; 365 mUsage = usage; 366 mMaxProducerBuffers = maxBuffers; 367 368 // Configure consumer-side ANativeWindow interface 369 370 res = native_window_api_connect(mConsumerInterface.get(), 371 NATIVE_WINDOW_API_CAMERA); 372 if (res != OK) { 373 ALOGE("%s: Unable to connect to native window for stream %d", 374 __FUNCTION__, mId); 375 mState = ALLOCATED; 376 return res; 377 } 378 379 res = native_window_set_usage(mConsumerInterface.get(), mUsage); 380 if (res != OK) { 381 ALOGE("%s: Unable to configure usage %08x for stream %d", 382 __FUNCTION__, mUsage, mId); 383 mState = CONNECTED; 384 return res; 385 } 386 387 res = native_window_set_buffers_geometry(mConsumerInterface.get(), 388 mWidth, mHeight, mFormat); 389 if (res != OK) { 390 ALOGE("%s: Unable to configure buffer geometry" 391 " %d x %d, format 0x%x for stream %d", 392 __FUNCTION__, mWidth, mHeight, mFormat, mId); 393 mState = CONNECTED; 394 return res; 395 } 396 397 int maxConsumerBuffers; 398 res = mConsumerInterface->query(mConsumerInterface.get(), 399 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers); 400 if (res != OK) { 401 ALOGE("%s: Unable to query consumer undequeued" 402 " buffer count for stream %d", __FUNCTION__, mId); 403 mState = CONNECTED; 404 return res; 405 } 406 mMaxConsumerBuffers = maxConsumerBuffers; 407 408 ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__, 409 mMaxProducerBuffers, mMaxConsumerBuffers); 410 411 int totalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers; 412 413 res = native_window_set_buffer_count(mConsumerInterface.get(), 414 totalBuffers); 415 if (res != OK) { 416 ALOGE("%s: Unable to set buffer count for stream %d", 417 __FUNCTION__, mId); 418 mState = CONNECTED; 419 return res; 420 } 421 422 // Register allocated buffers with HAL device 423 buffer_handle_t *buffers = new buffer_handle_t[totalBuffers]; 424 ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[totalBuffers]; 425 int bufferIdx = 0; 426 for (; bufferIdx < totalBuffers; bufferIdx++) { 427 res = native_window_dequeue_buffer_and_wait(mConsumerInterface.get(), 428 &anwBuffers[bufferIdx]); 429 if (res != OK) { 430 ALOGE("%s: Unable to dequeue buffer %d for initial registration for" 431 "stream %d", __FUNCTION__, bufferIdx, mId); 432 mState = CONNECTED; 433 goto cleanUpBuffers; 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], -1); 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 489const camera2_stream_ops *StreamAdapter::getStreamOps() { 490 return static_cast<camera2_stream_ops *>(this); 491} 492 493ANativeWindow* StreamAdapter::toANW(const camera2_stream_ops_t *w) { 494 return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get(); 495} 496 497int StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w, 498 buffer_handle_t** buffer) { 499 int res; 500 int state = static_cast<const 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 = native_window_dequeue_buffer_and_wait(a, &anb); 509 if (res != OK) return res; 510 511 *buffer = &(anb->handle); 512 513 return res; 514} 515 516int StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w, 517 int64_t timestamp, 518 buffer_handle_t* buffer) { 519 int state = static_cast<const StreamAdapter*>(w)->mState; 520 if (state != ACTIVE) { 521 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); 522 return INVALID_OPERATION; 523 } 524 ANativeWindow *a = toANW(w); 525 status_t err; 526 err = native_window_set_buffers_timestamp(a, timestamp); 527 if (err != OK) return err; 528 return a->queueBuffer(a, 529 container_of(buffer, ANativeWindowBuffer, handle), -1); 530} 531 532int StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w, 533 buffer_handle_t* buffer) { 534 int state = static_cast<const StreamAdapter*>(w)->mState; 535 if (state != ACTIVE) { 536 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); 537 return INVALID_OPERATION; 538 } 539 ANativeWindow *a = toANW(w); 540 return a->cancelBuffer(a, 541 container_of(buffer, ANativeWindowBuffer, handle), -1); 542} 543 544int StreamAdapter::set_crop(const camera2_stream_ops_t* w, 545 int left, int top, int right, int bottom) { 546 int state = static_cast<const StreamAdapter*>(w)->mState; 547 if (state != ACTIVE) { 548 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); 549 return INVALID_OPERATION; 550 } 551 ANativeWindow *a = toANW(w); 552 android_native_rect_t crop = { left, top, right, bottom }; 553 return native_window_set_crop(a, &crop); 554} 555 556/** 557 * FrameWaiter 558 */ 559 560FrameWaiter::FrameWaiter(): 561 mPendingFrames(0) { 562} 563 564status_t FrameWaiter::waitForFrame(nsecs_t timeout) { 565 status_t res; 566 Mutex::Autolock lock(mMutex); 567 while (mPendingFrames == 0) { 568 res = mCondition.waitRelative(mMutex, timeout); 569 if (res != OK) return res; 570 } 571 mPendingFrames--; 572 return OK; 573} 574 575void FrameWaiter::onFrameAvailable() { 576 Mutex::Autolock lock(mMutex); 577 mPendingFrames++; 578 mCondition.signal(); 579} 580 581} // namespace android 582