Eino-Ville Talvala | 61ab9f9 | 2012-05-17 10:30:54 -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 | #define LOG_TAG "Camera2Device" |
| 18 | //#define LOG_NDEBUG 0 |
| 19 | |
| 20 | #include <utils/Log.h> |
| 21 | #include "Camera2Device.h" |
| 22 | |
| 23 | namespace android { |
| 24 | |
Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame^] | 25 | Camera2Device::Camera2Device(int id): |
| 26 | mId(id), |
Eino-Ville Talvala | 61ab9f9 | 2012-05-17 10:30:54 -0700 | [diff] [blame] | 27 | mDevice(NULL) |
| 28 | { |
| 29 | |
| 30 | } |
| 31 | |
| 32 | Camera2Device::~Camera2Device() |
| 33 | { |
| 34 | if (mDevice) { |
| 35 | status_t res; |
| 36 | res = mDevice->common.close(&mDevice->common); |
| 37 | if (res != OK) { |
Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame^] | 38 | ALOGE("%s: Could not close camera %d: %s (%d)", |
| 39 | __FUNCTION__, |
| 40 | mId, strerror(-res), res); |
Eino-Ville Talvala | 61ab9f9 | 2012-05-17 10:30:54 -0700 | [diff] [blame] | 41 | } |
Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame^] | 42 | mDevice = NULL; |
Eino-Ville Talvala | 61ab9f9 | 2012-05-17 10:30:54 -0700 | [diff] [blame] | 43 | } |
| 44 | } |
| 45 | |
Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame^] | 46 | status_t Camera2Device::initialize(camera_module_t *module) |
Eino-Ville Talvala | 61ab9f9 | 2012-05-17 10:30:54 -0700 | [diff] [blame] | 47 | { |
| 48 | status_t res; |
Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame^] | 49 | char name[10]; |
| 50 | snprintf(name, sizeof(name), "%d", mId); |
| 51 | |
| 52 | res = module->common.methods->open(&module->common, name, |
Eino-Ville Talvala | 61ab9f9 | 2012-05-17 10:30:54 -0700 | [diff] [blame] | 53 | reinterpret_cast<hw_device_t**>(&mDevice)); |
| 54 | |
| 55 | if (res != OK) { |
Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame^] | 56 | ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__, |
| 57 | mId, strerror(-res), res); |
Eino-Ville Talvala | 61ab9f9 | 2012-05-17 10:30:54 -0700 | [diff] [blame] | 58 | return res; |
| 59 | } |
| 60 | |
| 61 | if (mDevice->common.version != CAMERA_DEVICE_API_VERSION_2_0) { |
Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame^] | 62 | ALOGE("%s: Could not open camera %d: " |
| 63 | "Camera device is not version %x, reports %x instead", |
| 64 | __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_2_0, |
| 65 | mDevice->common.version); |
Eino-Ville Talvala | 61ab9f9 | 2012-05-17 10:30:54 -0700 | [diff] [blame] | 66 | return BAD_VALUE; |
| 67 | } |
| 68 | |
Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame^] | 69 | camera_info info; |
| 70 | res = module->get_camera_info(mId, &info); |
| 71 | if (res != OK ) return res; |
| 72 | |
| 73 | if (info.device_version != mDevice->common.version) { |
| 74 | ALOGE("%s: HAL reporting mismatched camera_info version (%x)" |
| 75 | " and device version (%x).", __FUNCTION__, |
| 76 | mDevice->common.version, info.device_version); |
| 77 | return BAD_VALUE; |
| 78 | } |
| 79 | |
| 80 | mDeviceInfo = info.static_camera_characteristics; |
| 81 | |
| 82 | res = mDevice->ops->set_request_queue_src_ops(mDevice, |
| 83 | mRequestQueue.getToConsumerInterface()); |
| 84 | if (res != OK) return res; |
| 85 | |
| 86 | res = mDevice->ops->set_frame_queue_dst_ops(mDevice, |
| 87 | mFrameQueue.getToProducerInterface()); |
| 88 | if (res != OK) return res; |
| 89 | |
| 90 | res = mDevice->ops->get_metadata_vendor_tag_ops(mDevice, &mVendorTagOps); |
| 91 | if (res != OK ) return res; |
| 92 | |
Eino-Ville Talvala | 61ab9f9 | 2012-05-17 10:30:54 -0700 | [diff] [blame] | 93 | return OK; |
| 94 | } |
| 95 | |
Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame^] | 96 | status_t Camera2Device::setStreamingRequest(camera_metadata_t* request) |
| 97 | { |
| 98 | mRequestQueue.setStreamSlot(request); |
| 99 | return OK; |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * Camera2Device::MetadataQueue |
| 104 | */ |
| 105 | |
| 106 | Camera2Device::MetadataQueue::MetadataQueue(): |
| 107 | mDevice(NULL), |
| 108 | mFrameCount(0), |
| 109 | mCount(0), |
| 110 | mStreamSlotCount(0), |
| 111 | mSignalConsumer(true) |
| 112 | { |
| 113 | camera2_request_queue_src_ops::dequeue_request = consumer_dequeue; |
| 114 | camera2_request_queue_src_ops::request_count = consumer_buffer_count; |
| 115 | camera2_request_queue_src_ops::free_request = consumer_free; |
| 116 | |
| 117 | camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue; |
| 118 | camera2_frame_queue_dst_ops::cancel_frame = producer_cancel; |
| 119 | camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue; |
| 120 | } |
| 121 | |
| 122 | Camera2Device::MetadataQueue::~MetadataQueue() { |
| 123 | Mutex::Autolock l(mMutex); |
| 124 | freeBuffers(mEntries.begin(), mEntries.end()); |
| 125 | freeBuffers(mStreamSlot.begin(), mStreamSlot.end()); |
| 126 | } |
| 127 | |
| 128 | // Interface to camera2 HAL as consumer (input requests/reprocessing) |
| 129 | const camera2_request_queue_src_ops_t* |
| 130 | Camera2Device::MetadataQueue::getToConsumerInterface() { |
| 131 | return static_cast<camera2_request_queue_src_ops_t*>(this); |
| 132 | } |
| 133 | |
| 134 | void Camera2Device::MetadataQueue::setFromConsumerInterface(camera2_device_t *d) { |
| 135 | Mutex::Autolock l(mMutex); |
| 136 | mDevice = d; |
| 137 | } |
| 138 | |
| 139 | const camera2_frame_queue_dst_ops_t* |
| 140 | Camera2Device::MetadataQueue::getToProducerInterface() { |
| 141 | return static_cast<camera2_frame_queue_dst_ops_t*>(this); |
| 142 | } |
| 143 | |
| 144 | // Real interfaces |
| 145 | status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) { |
| 146 | Mutex::Autolock l(mMutex); |
| 147 | |
| 148 | mCount++; |
| 149 | mEntries.push_back(buf); |
| 150 | notEmpty.signal(); |
| 151 | |
| 152 | if (mSignalConsumer && mDevice != NULL) { |
| 153 | mSignalConsumer = false; |
| 154 | |
| 155 | mMutex.unlock(); |
| 156 | ALOGV("%s: Signaling consumer", __FUNCTION__); |
| 157 | mDevice->ops->notify_request_queue_not_empty(mDevice); |
| 158 | mMutex.lock(); |
| 159 | } |
| 160 | return OK; |
| 161 | } |
| 162 | |
| 163 | int Camera2Device::MetadataQueue::getBufferCount() { |
| 164 | Mutex::Autolock l(mMutex); |
| 165 | if (mStreamSlotCount > 0) { |
| 166 | return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS; |
| 167 | } |
| 168 | return mCount; |
| 169 | } |
| 170 | |
| 171 | status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf, |
| 172 | bool incrementCount) |
| 173 | { |
| 174 | Mutex::Autolock l(mMutex); |
| 175 | |
| 176 | if (mCount == 0) { |
| 177 | if (mStreamSlotCount == 0) { |
| 178 | ALOGV("%s: Empty", __FUNCTION__); |
| 179 | *buf = NULL; |
| 180 | mSignalConsumer = true; |
| 181 | return OK; |
| 182 | } |
| 183 | ALOGV("%s: Streaming %d frames to queue", __FUNCTION__, |
| 184 | mStreamSlotCount); |
| 185 | |
| 186 | for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin(); |
| 187 | slotEntry != mStreamSlot.end(); |
| 188 | slotEntry++ ) { |
| 189 | size_t entries = get_camera_metadata_entry_count(*slotEntry); |
| 190 | size_t dataBytes = get_camera_metadata_data_count(*slotEntry); |
| 191 | |
| 192 | camera_metadata_t *copy = |
| 193 | allocate_camera_metadata(entries, dataBytes); |
| 194 | append_camera_metadata(copy, *slotEntry); |
| 195 | mEntries.push_back(copy); |
| 196 | } |
| 197 | mCount = mStreamSlotCount; |
| 198 | } |
| 199 | ALOGV("MetadataQueue: deque (%d buffers)", mCount); |
| 200 | camera_metadata_t *b = *(mEntries.begin()); |
| 201 | mEntries.erase(mEntries.begin()); |
| 202 | |
| 203 | if (incrementCount) { |
| 204 | add_camera_metadata_entry(b, |
| 205 | ANDROID_REQUEST_FRAME_COUNT, |
| 206 | (void**)&mFrameCount, 1); |
| 207 | mFrameCount++; |
| 208 | } |
| 209 | |
| 210 | *buf = b; |
| 211 | mCount--; |
| 212 | |
| 213 | return OK; |
| 214 | } |
| 215 | |
| 216 | status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout) |
| 217 | { |
| 218 | Mutex::Autolock l(mMutex); |
| 219 | status_t res; |
| 220 | while (mCount == 0) { |
| 221 | res = notEmpty.waitRelative(mMutex,timeout); |
| 222 | if (res != OK) return res; |
| 223 | } |
| 224 | return OK; |
| 225 | } |
| 226 | |
| 227 | status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf) |
| 228 | { |
| 229 | Mutex::Autolock l(mMutex); |
| 230 | if (buf == NULL) { |
| 231 | freeBuffers(mStreamSlot.begin(), mStreamSlot.end()); |
| 232 | mStreamSlotCount = 0; |
| 233 | return OK; |
| 234 | } |
| 235 | if (mStreamSlotCount > 1) { |
| 236 | List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin(); |
| 237 | freeBuffers(++mStreamSlot.begin(), mStreamSlot.end()); |
| 238 | mStreamSlotCount = 1; |
| 239 | } |
| 240 | if (mStreamSlotCount == 1) { |
| 241 | free_camera_metadata( *(mStreamSlot.begin()) ); |
| 242 | *(mStreamSlot.begin()) = buf; |
| 243 | } else { |
| 244 | mStreamSlot.push_front(buf); |
| 245 | mStreamSlotCount = 1; |
| 246 | } |
| 247 | return OK; |
| 248 | } |
| 249 | |
| 250 | status_t Camera2Device::MetadataQueue::setStreamSlot( |
| 251 | const List<camera_metadata_t*> &bufs) |
| 252 | { |
| 253 | Mutex::Autolock l(mMutex); |
| 254 | if (mStreamSlotCount > 0) { |
| 255 | freeBuffers(mStreamSlot.begin(), mStreamSlot.end()); |
| 256 | } |
| 257 | mStreamSlot = bufs; |
| 258 | mStreamSlotCount = mStreamSlot.size(); |
| 259 | |
| 260 | return OK; |
| 261 | } |
| 262 | |
| 263 | status_t Camera2Device::MetadataQueue::freeBuffers( |
| 264 | List<camera_metadata_t*>::iterator start, |
| 265 | List<camera_metadata_t*>::iterator end) |
| 266 | { |
| 267 | while (start != end) { |
| 268 | free_camera_metadata(*start); |
| 269 | start = mStreamSlot.erase(start); |
| 270 | } |
| 271 | return OK; |
| 272 | } |
| 273 | |
| 274 | Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance( |
| 275 | const camera2_request_queue_src_ops_t *q) |
| 276 | { |
| 277 | const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q); |
| 278 | return const_cast<MetadataQueue*>(cmq); |
| 279 | } |
| 280 | |
| 281 | Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance( |
| 282 | const camera2_frame_queue_dst_ops_t *q) |
| 283 | { |
| 284 | const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q); |
| 285 | return const_cast<MetadataQueue*>(cmq); |
| 286 | } |
| 287 | |
| 288 | int Camera2Device::MetadataQueue::consumer_buffer_count( |
| 289 | const camera2_request_queue_src_ops_t *q) |
| 290 | { |
| 291 | MetadataQueue *queue = getInstance(q); |
| 292 | return queue->getBufferCount(); |
| 293 | } |
| 294 | |
| 295 | int Camera2Device::MetadataQueue::consumer_dequeue( |
| 296 | const camera2_request_queue_src_ops_t *q, |
| 297 | camera_metadata_t **buffer) |
| 298 | { |
| 299 | MetadataQueue *queue = getInstance(q); |
| 300 | return queue->dequeue(buffer, true); |
| 301 | } |
| 302 | |
| 303 | int Camera2Device::MetadataQueue::consumer_free( |
| 304 | const camera2_request_queue_src_ops_t *q, |
| 305 | camera_metadata_t *old_buffer) |
| 306 | { |
| 307 | MetadataQueue *queue = getInstance(q); |
| 308 | free_camera_metadata(old_buffer); |
| 309 | return OK; |
| 310 | } |
| 311 | |
| 312 | int Camera2Device::MetadataQueue::producer_dequeue( |
| 313 | const camera2_frame_queue_dst_ops_t *q, |
| 314 | size_t entries, size_t bytes, |
| 315 | camera_metadata_t **buffer) |
| 316 | { |
| 317 | camera_metadata_t *new_buffer = |
| 318 | allocate_camera_metadata(entries, bytes); |
| 319 | if (new_buffer == NULL) return NO_MEMORY; |
| 320 | *buffer = new_buffer; |
| 321 | return OK; |
| 322 | } |
| 323 | |
| 324 | int Camera2Device::MetadataQueue::producer_cancel( |
| 325 | const camera2_frame_queue_dst_ops_t *q, |
| 326 | camera_metadata_t *old_buffer) |
| 327 | { |
| 328 | free_camera_metadata(old_buffer); |
| 329 | return OK; |
| 330 | } |
| 331 | |
| 332 | int Camera2Device::MetadataQueue::producer_enqueue( |
| 333 | const camera2_frame_queue_dst_ops_t *q, |
| 334 | camera_metadata_t *filled_buffer) |
| 335 | { |
| 336 | MetadataQueue *queue = getInstance(q); |
| 337 | return queue->enqueue(filled_buffer); |
| 338 | } |
| 339 | |
Eino-Ville Talvala | 61ab9f9 | 2012-05-17 10:30:54 -0700 | [diff] [blame] | 340 | |
| 341 | }; // namespace android |