| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 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 |  | 
|  | 25 | namespace android { | 
|  | 26 |  | 
|  | 27 | /** | 
|  | 28 | * MetadataQueue | 
|  | 29 | */ | 
|  | 30 |  | 
|  | 31 | MetadataQueue::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 |  | 
|  | 47 | MetadataQueue::~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) | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 53 | const camera2_request_queue_src_ops_t* MetadataQueue::getToConsumerInterface() { | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 54 | return static_cast<camera2_request_queue_src_ops_t*>(this); | 
|  | 55 | } | 
|  | 56 |  | 
|  | 57 | void MetadataQueue::setFromConsumerInterface(camera2_device_t *d) { | 
|  | 58 | mDevice = d; | 
|  | 59 | } | 
|  | 60 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 61 | const camera2_frame_queue_dst_ops_t* MetadataQueue::getToProducerInterface() { | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 62 | return static_cast<camera2_frame_queue_dst_ops_t*>(this); | 
|  | 63 | } | 
|  | 64 |  | 
|  | 65 | // Real interfaces | 
|  | 66 | status_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 |  | 
|  | 84 | int MetadataQueue::getBufferCount() { | 
|  | 85 | Mutex::Autolock l(mMutex); | 
|  | 86 | if (mStreamSlotCount > 0) { | 
|  | 87 | return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS; | 
|  | 88 | } | 
|  | 89 | return mCount; | 
|  | 90 | } | 
|  | 91 |  | 
|  | 92 | status_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 |  | 
|  | 134 | status_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 |  | 
|  | 144 | status_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 |  | 
|  | 165 | status_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 |  | 
|  | 175 | status_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 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 184 | MetadataQueue* 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 |  | 
|  | 190 | MetadataQueue* 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 |  | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 196 | int MetadataQueue::consumer_buffer_count( | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 197 | const camera2_request_queue_src_ops_t *q) { | 
|  | 198 | MetadataQueue *queue = getInstance(q); | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 199 | return queue->getBufferCount(); | 
|  | 200 | } | 
|  | 201 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 202 | int MetadataQueue::consumer_dequeue(const camera2_request_queue_src_ops_t *q, | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 203 | camera_metadata_t **buffer) { | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 204 | MetadataQueue *queue = getInstance(q); | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 205 | return queue->dequeue(buffer, true); | 
|  | 206 | } | 
|  | 207 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 208 | int MetadataQueue::consumer_free(const camera2_request_queue_src_ops_t *q, | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 209 | camera_metadata_t *old_buffer) { | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 210 | MetadataQueue *queue = getInstance(q); | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 211 | free_camera_metadata(old_buffer); | 
|  | 212 | return OK; | 
|  | 213 | } | 
|  | 214 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 215 | int MetadataQueue::producer_dequeue(const camera2_frame_queue_dst_ops_t *q, | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 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 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 225 | int MetadataQueue::producer_cancel(const camera2_frame_queue_dst_ops_t *q, | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 226 | camera_metadata_t *old_buffer) { | 
|  | 227 | free_camera_metadata(old_buffer); | 
|  | 228 | return OK; | 
|  | 229 | } | 
|  | 230 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 231 | int MetadataQueue::producer_enqueue(const camera2_frame_queue_dst_ops_t *q, | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 232 | camera_metadata_t *filled_buffer) { | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 233 | MetadataQueue *queue = getInstance(q); | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 234 | return queue->enqueue(filled_buffer); | 
|  | 235 | } | 
|  | 236 |  | 
|  | 237 | /** | 
|  | 238 | * NotifierListener | 
|  | 239 | */ | 
|  | 240 |  | 
|  | 241 | NotifierListener::NotifierListener() { | 
|  | 242 | } | 
|  | 243 |  | 
|  | 244 | status_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 |  | 
|  | 253 | status_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 |  | 
|  | 262 | status_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 |  | 
|  | 273 | int NotifierListener::numNotifications() { | 
|  | 274 | Mutex::Autolock l(mMutex); | 
|  | 275 | return mNotifications.size(); | 
|  | 276 | } | 
|  | 277 |  | 
|  | 278 | status_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 |  | 
|  | 290 | void 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 |  | 
|  | 299 | void 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 |  | 
|  | 317 | StreamAdapter::StreamAdapter(sp<ISurfaceTexture> consumer): | 
|  | 318 | mState(UNINITIALIZED), mDevice(NULL), | 
|  | 319 | mId(-1), | 
|  | 320 | mWidth(0), mHeight(0), mFormatRequested(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 |  | 
|  | 329 | StreamAdapter::~StreamAdapter() { | 
|  | 330 | disconnect(); | 
|  | 331 | } | 
|  | 332 |  | 
|  | 333 | status_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 | mFormatRequested = format; | 
|  | 346 |  | 
|  | 347 | // Allocate device-side stream interface | 
|  | 348 |  | 
|  | 349 | uint32_t id; | 
|  | 350 | uint32_t formatActual; | 
|  | 351 | uint32_t usage; | 
|  | 352 | uint32_t maxBuffers = 2; | 
|  | 353 | res = d->ops->allocate_stream(d, | 
|  | 354 | mWidth, mHeight, mFormatRequested, 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 | mFormat = formatActual; | 
|  | 366 | mUsage = usage; | 
|  | 367 | mMaxProducerBuffers = maxBuffers; | 
|  | 368 |  | 
|  | 369 | // Configure consumer-side ANativeWindow interface | 
|  | 370 |  | 
|  | 371 | res = native_window_api_connect(mConsumerInterface.get(), | 
|  | 372 | NATIVE_WINDOW_API_CAMERA); | 
|  | 373 | if (res != OK) { | 
|  | 374 | ALOGE("%s: Unable to connect to native window for stream %d", | 
|  | 375 | __FUNCTION__, mId); | 
|  | 376 | mState = ALLOCATED; | 
|  | 377 | return res; | 
|  | 378 | } | 
|  | 379 |  | 
|  | 380 | res = native_window_set_usage(mConsumerInterface.get(), mUsage); | 
|  | 381 | if (res != OK) { | 
|  | 382 | ALOGE("%s: Unable to configure usage %08x for stream %d", | 
|  | 383 | __FUNCTION__, mUsage, mId); | 
|  | 384 | mState = CONNECTED; | 
|  | 385 | return res; | 
|  | 386 | } | 
|  | 387 |  | 
|  | 388 | res = native_window_set_buffers_geometry(mConsumerInterface.get(), | 
|  | 389 | mWidth, mHeight, mFormat); | 
|  | 390 | if (res != OK) { | 
|  | 391 | ALOGE("%s: Unable to configure buffer geometry" | 
|  | 392 | " %d x %d, format 0x%x for stream %d", | 
|  | 393 | __FUNCTION__, mWidth, mHeight, mFormat, mId); | 
|  | 394 | mState = CONNECTED; | 
|  | 395 | return res; | 
|  | 396 | } | 
|  | 397 |  | 
|  | 398 | int maxConsumerBuffers; | 
|  | 399 | res = mConsumerInterface->query(mConsumerInterface.get(), | 
|  | 400 | NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers); | 
|  | 401 | if (res != OK) { | 
|  | 402 | ALOGE("%s: Unable to query consumer undequeued" | 
|  | 403 | " buffer count for stream %d", __FUNCTION__, mId); | 
|  | 404 | mState = CONNECTED; | 
|  | 405 | return res; | 
|  | 406 | } | 
|  | 407 | mMaxConsumerBuffers = maxConsumerBuffers; | 
|  | 408 |  | 
|  | 409 | ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__, | 
|  | 410 | mMaxProducerBuffers, mMaxConsumerBuffers); | 
|  | 411 |  | 
|  | 412 | int totalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers; | 
|  | 413 |  | 
|  | 414 | res = native_window_set_buffer_count(mConsumerInterface.get(), | 
|  | 415 | totalBuffers); | 
|  | 416 | if (res != OK) { | 
|  | 417 | ALOGE("%s: Unable to set buffer count for stream %d", | 
|  | 418 | __FUNCTION__, mId); | 
|  | 419 | mState = CONNECTED; | 
|  | 420 | return res; | 
|  | 421 | } | 
|  | 422 |  | 
|  | 423 | // Register allocated buffers with HAL device | 
|  | 424 | buffer_handle_t *buffers = new buffer_handle_t[totalBuffers]; | 
|  | 425 | ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[totalBuffers]; | 
|  | 426 | int bufferIdx = 0; | 
|  | 427 | for (; bufferIdx < totalBuffers; bufferIdx++) { | 
|  | 428 | res = mConsumerInterface->dequeueBuffer(mConsumerInterface.get(), | 
|  | 429 | &anwBuffers[bufferIdx]); | 
|  | 430 | if (res != OK) { | 
|  | 431 | ALOGE("%s: Unable to dequeue buffer %d for initial registration for" | 
|  | 432 | "stream %d", __FUNCTION__, bufferIdx, mId); | 
|  | 433 | mState = CONNECTED; | 
|  | 434 | goto cleanUpBuffers; | 
|  | 435 | } | 
|  | 436 |  | 
|  | 437 | res = mConsumerInterface->lockBuffer(mConsumerInterface.get(), | 
|  | 438 | anwBuffers[bufferIdx]); | 
|  | 439 | if (res != OK) { | 
|  | 440 | ALOGE("%s: Unable to lock buffer %d for initial registration for" | 
|  | 441 | "stream %d", __FUNCTION__, bufferIdx, mId); | 
|  | 442 | mState = CONNECTED; | 
|  | 443 | bufferIdx++; | 
|  | 444 | goto cleanUpBuffers; | 
|  | 445 | } | 
|  | 446 |  | 
|  | 447 | buffers[bufferIdx] = anwBuffers[bufferIdx]->handle; | 
|  | 448 | } | 
|  | 449 |  | 
|  | 450 | res = mDevice->ops->register_stream_buffers(mDevice, | 
|  | 451 | mId, | 
|  | 452 | totalBuffers, | 
|  | 453 | buffers); | 
|  | 454 | if (res != OK) { | 
|  | 455 | ALOGE("%s: Unable to register buffers with HAL device for stream %d", | 
|  | 456 | __FUNCTION__, mId); | 
|  | 457 | mState = CONNECTED; | 
|  | 458 | } else { | 
|  | 459 | mState = ACTIVE; | 
|  | 460 | } | 
|  | 461 |  | 
|  | 462 | cleanUpBuffers: | 
|  | 463 | for (int i = 0; i < bufferIdx; i++) { | 
|  | 464 | res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(), | 
|  | 465 | anwBuffers[i]); | 
|  | 466 | } | 
|  | 467 | delete anwBuffers; | 
|  | 468 | delete buffers; | 
|  | 469 |  | 
|  | 470 | return res; | 
|  | 471 | } | 
|  | 472 |  | 
|  | 473 | status_t StreamAdapter::disconnect() { | 
|  | 474 | status_t res; | 
|  | 475 | if (mState >= ALLOCATED) { | 
|  | 476 | res = mDevice->ops->release_stream(mDevice, mId); | 
|  | 477 | if (res != OK) { | 
|  | 478 | ALOGE("%s: Unable to release stream %d", | 
|  | 479 | __FUNCTION__, mId); | 
|  | 480 | return res; | 
|  | 481 | } | 
|  | 482 | } | 
|  | 483 | if (mState >= CONNECTED) { | 
|  | 484 | res = native_window_api_disconnect(mConsumerInterface.get(), | 
|  | 485 | NATIVE_WINDOW_API_CAMERA); | 
|  | 486 | if (res != OK) { | 
|  | 487 | ALOGE("%s: Unable to disconnect stream %d from native window", | 
|  | 488 | __FUNCTION__, mId); | 
|  | 489 | return res; | 
|  | 490 | } | 
|  | 491 | } | 
|  | 492 | mId = -1; | 
|  | 493 | mState = DISCONNECTED; | 
|  | 494 | return OK; | 
|  | 495 | } | 
|  | 496 |  | 
|  | 497 | int StreamAdapter::getId() { | 
|  | 498 | return mId; | 
|  | 499 | } | 
|  | 500 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 501 | const camera2_stream_ops *StreamAdapter::getStreamOps() { | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 502 | return static_cast<camera2_stream_ops *>(this); | 
|  | 503 | } | 
|  | 504 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 505 | ANativeWindow* StreamAdapter::toANW(const camera2_stream_ops_t *w) { | 
|  | 506 | return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get(); | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 507 | } | 
|  | 508 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 509 | int StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w, | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 510 | buffer_handle_t** buffer) { | 
|  | 511 | int res; | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 512 | int state = static_cast<const StreamAdapter*>(w)->mState; | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 513 | if (state != ACTIVE) { | 
|  | 514 | ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); | 
|  | 515 | return INVALID_OPERATION; | 
|  | 516 | } | 
|  | 517 |  | 
|  | 518 | ANativeWindow *a = toANW(w); | 
|  | 519 | ANativeWindowBuffer* anb; | 
|  | 520 | res = a->dequeueBuffer(a, &anb); | 
|  | 521 | if (res != OK) return res; | 
|  | 522 | res = a->lockBuffer(a, anb); | 
|  | 523 | if (res != OK) return res; | 
|  | 524 |  | 
|  | 525 | *buffer = &(anb->handle); | 
|  | 526 |  | 
|  | 527 | return res; | 
|  | 528 | } | 
|  | 529 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 530 | int StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w, | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 531 | int64_t timestamp, | 
|  | 532 | buffer_handle_t* buffer) { | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 533 | int state = static_cast<const StreamAdapter*>(w)->mState; | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 534 | if (state != ACTIVE) { | 
|  | 535 | ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); | 
|  | 536 | return INVALID_OPERATION; | 
|  | 537 | } | 
|  | 538 | ANativeWindow *a = toANW(w); | 
|  | 539 | status_t err; | 
|  | 540 | err = native_window_set_buffers_timestamp(a, timestamp); | 
|  | 541 | if (err != OK) return err; | 
|  | 542 | return a->queueBuffer(a, | 
|  | 543 | container_of(buffer, ANativeWindowBuffer, handle)); | 
|  | 544 | } | 
|  | 545 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 546 | int StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w, | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 547 | buffer_handle_t* buffer) { | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 548 | int state = static_cast<const StreamAdapter*>(w)->mState; | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 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 | return a->cancelBuffer(a, | 
|  | 555 | container_of(buffer, ANativeWindowBuffer, handle)); | 
|  | 556 | } | 
|  | 557 |  | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 558 | int StreamAdapter::set_crop(const camera2_stream_ops_t* w, | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 559 | int left, int top, int right, int bottom) { | 
| Eino-Ville Talvala | 08a6e5e | 2012-05-17 17:54:56 -0700 | [diff] [blame] | 560 | int state = static_cast<const StreamAdapter*>(w)->mState; | 
| Eino-Ville Talvala | 567b4a2 | 2012-04-23 09:29:38 -0700 | [diff] [blame] | 561 | if (state != ACTIVE) { | 
|  | 562 | ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state); | 
|  | 563 | return INVALID_OPERATION; | 
|  | 564 | } | 
|  | 565 | ANativeWindow *a = toANW(w); | 
|  | 566 | android_native_rect_t crop = { left, top, right, bottom }; | 
|  | 567 | return native_window_set_crop(a, &crop); | 
|  | 568 | } | 
|  | 569 |  | 
|  | 570 | /** | 
|  | 571 | * FrameWaiter | 
|  | 572 | */ | 
|  | 573 |  | 
|  | 574 | FrameWaiter::FrameWaiter(): | 
|  | 575 | mPendingFrames(0) { | 
|  | 576 | } | 
|  | 577 |  | 
|  | 578 | status_t FrameWaiter::waitForFrame(nsecs_t timeout) { | 
|  | 579 | status_t res; | 
|  | 580 | Mutex::Autolock lock(mMutex); | 
|  | 581 | while (mPendingFrames == 0) { | 
|  | 582 | res = mCondition.waitRelative(mMutex, timeout); | 
|  | 583 | if (res != OK) return res; | 
|  | 584 | } | 
|  | 585 | mPendingFrames--; | 
|  | 586 | return OK; | 
|  | 587 | } | 
|  | 588 |  | 
|  | 589 | void FrameWaiter::onFrameAvailable() { | 
|  | 590 | Mutex::Autolock lock(mMutex); | 
|  | 591 | mPendingFrames++; | 
|  | 592 | mCondition.signal(); | 
|  | 593 | } | 
|  | 594 |  | 
|  | 595 | } // namespace android |