blob: 5a37c8d7dabe326e2b1dcec93fe7aa5e7f8f39bf [file] [log] [blame]
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -07001/*
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
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -070019//#define LOG_NNDEBUG 0 // Per-frame verbose logging
20
21#ifdef LOG_NNDEBUG
22#define ALOGVV(...) ALOGV(__VA_ARGS__)
23#else
24#define ALOGVV(...) ((void)0)
25#endif
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070026
27#include <utils/Log.h>
28#include "Camera2Device.h"
29
30namespace android {
31
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070032Camera2Device::Camera2Device(int id):
33 mId(id),
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070034 mDevice(NULL)
35{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070036 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070037}
38
39Camera2Device::~Camera2Device()
40{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070041 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070042 if (mDevice) {
43 status_t res;
44 res = mDevice->common.close(&mDevice->common);
45 if (res != OK) {
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070046 ALOGE("%s: Could not close camera %d: %s (%d)",
47 __FUNCTION__,
48 mId, strerror(-res), res);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070049 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070050 mDevice = NULL;
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070051 }
52}
53
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070054status_t Camera2Device::initialize(camera_module_t *module)
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070055{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070056 ALOGV("%s: E", __FUNCTION__);
57
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070058 status_t res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070059 char name[10];
60 snprintf(name, sizeof(name), "%d", mId);
61
62 res = module->common.methods->open(&module->common, name,
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070063 reinterpret_cast<hw_device_t**>(&mDevice));
64
65 if (res != OK) {
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070066 ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
67 mId, strerror(-res), res);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070068 return res;
69 }
70
71 if (mDevice->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070072 ALOGE("%s: Could not open camera %d: "
73 "Camera device is not version %x, reports %x instead",
74 __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_2_0,
75 mDevice->common.version);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070076 return BAD_VALUE;
77 }
78
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070079 camera_info info;
80 res = module->get_camera_info(mId, &info);
81 if (res != OK ) return res;
82
83 if (info.device_version != mDevice->common.version) {
84 ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
85 " and device version (%x).", __FUNCTION__,
86 mDevice->common.version, info.device_version);
87 return BAD_VALUE;
88 }
89
90 mDeviceInfo = info.static_camera_characteristics;
91
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070092 res = mRequestQueue.setConsumerDevice(mDevice);
93 if (res != OK) {
94 ALOGE("%s: Camera %d: Unable to connect request queue to device: %s (%d)",
95 __FUNCTION__, mId, strerror(-res), res);
96 return res;
97 }
98 res = mFrameQueue.setProducerDevice(mDevice);
99 if (res != OK) {
100 ALOGE("%s: Camera %d: Unable to connect frame queue to device: %s (%d)",
101 __FUNCTION__, mId, strerror(-res), res);
102 return res;
103 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700104
105 res = mDevice->ops->get_metadata_vendor_tag_ops(mDevice, &mVendorTagOps);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700106 if (res != OK ) {
107 ALOGE("%s: Camera %d: Unable to retrieve tag ops from device: %s (%d)",
108 __FUNCTION__, mId, strerror(-res), res);
109 return res;
110 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700111
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700112 return OK;
113}
114
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700115status_t Camera2Device::dump(int fd, const Vector<String16>& args) {
116
117 String8 result;
118
119 result.appendFormat(" Camera2Device[%d] dump:\n", mId);
120
121 result.appendFormat(" Static camera information metadata:\n");
122 write(fd, result.string(), result.size());
123 dump_camera_metadata(mDeviceInfo, fd, 2);
124
125 result = " Request queue contents:\n";
126 write(fd, result.string(), result.size());
127 mRequestQueue.dump(fd, args);
128
129 result = " Frame queue contents:\n";
130 write(fd, result.string(), result.size());
131 mFrameQueue.dump(fd, args);
132
133 result = " Active streams:\n";
134 write(fd, result.string(), result.size());
135 for (StreamList::iterator s = mStreams.begin(); s != mStreams.end(); s++) {
136 (*s)->dump(fd, args);
137 }
138
139 result = " HAL device dump:\n";
140 write(fd, result.string(), result.size());
141
142 status_t res;
143 res = mDevice->ops->dump(mDevice, fd);
144
145 return res;
146}
147
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700148camera_metadata_t *Camera2Device::info() {
149 ALOGV("%s: E", __FUNCTION__);
150
151 return mDeviceInfo;
152}
153
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700154status_t Camera2Device::capture(camera_metadata_t* request) {
155 ALOGV("%s: E", __FUNCTION__);
156
157 mRequestQueue.enqueue(request);
158 return OK;
159}
160
161
162status_t Camera2Device::setStreamingRequest(camera_metadata_t* request) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700163 ALOGV("%s: E", __FUNCTION__);
164
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700165 mRequestQueue.setStreamSlot(request);
166 return OK;
167}
168
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700169status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700170 uint32_t width, uint32_t height, int format, size_t size, int *id) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700171 status_t res;
172 ALOGV("%s: E", __FUNCTION__);
173
174 sp<StreamAdapter> stream = new StreamAdapter(mDevice);
175
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700176 res = stream->connectToDevice(consumer, width, height, format, size);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700177 if (res != OK) {
178 ALOGE("%s: Camera %d: Unable to create stream (%d x %d, format %x):"
179 "%s (%d)",
180 __FUNCTION__, mId, width, height, format, strerror(-res), res);
181 return res;
182 }
183
184 *id = stream->getId();
185
186 mStreams.push_back(stream);
187 return OK;
188}
189
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700190status_t Camera2Device::getStreamInfo(int id,
191 uint32_t *width, uint32_t *height, uint32_t *format) {
192 ALOGV("%s: E", __FUNCTION__);
193 bool found = false;
194 StreamList::iterator streamI;
195 for (streamI = mStreams.begin();
196 streamI != mStreams.end(); streamI++) {
197 if ((*streamI)->getId() == id) {
198 found = true;
199 break;
200 }
201 }
202 if (!found) {
203 ALOGE("%s: Camera %d: Stream %d does not exist",
204 __FUNCTION__, mId, id);
205 return BAD_VALUE;
206 }
207
208 if (width) *width = (*streamI)->getWidth();
209 if (height) *height = (*streamI)->getHeight();
210 if (format) *format = (*streamI)->getFormat();
211
212 return OK;
213}
214
Eino-Ville Talvalac94cd192012-06-15 12:47:42 -0700215status_t Camera2Device::setStreamTransform(int id,
216 int transform) {
217 ALOGV("%s: E", __FUNCTION__);
218 bool found = false;
219 StreamList::iterator streamI;
220 for (streamI = mStreams.begin();
221 streamI != mStreams.end(); streamI++) {
222 if ((*streamI)->getId() == id) {
223 found = true;
224 break;
225 }
226 }
227 if (!found) {
228 ALOGE("%s: Camera %d: Stream %d does not exist",
229 __FUNCTION__, mId, id);
230 return BAD_VALUE;
231 }
232
233 return (*streamI)->setTransform(transform);
234}
235
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700236status_t Camera2Device::deleteStream(int id) {
237 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700238 bool found = false;
239 for (StreamList::iterator streamI = mStreams.begin();
240 streamI != mStreams.end(); streamI++) {
241 if ((*streamI)->getId() == id) {
Eino-Ville Talvala4ecfec32012-06-12 17:13:48 -0700242 status_t res = (*streamI)->disconnect();
243 if (res != OK) {
244 ALOGE("%s: Unable to disconnect stream %d from HAL device: "
245 "%s (%d)", __FUNCTION__, id, strerror(-res), res);
246 return res;
247 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700248 mStreams.erase(streamI);
249 found = true;
250 break;
251 }
252 }
253 if (!found) {
254 ALOGE("%s: Camera %d: Unable to find stream %d to delete",
255 __FUNCTION__, mId, id);
256 return BAD_VALUE;
257 }
258 return OK;
259}
260
261status_t Camera2Device::createDefaultRequest(int templateId,
262 camera_metadata_t **request) {
263 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700264 return mDevice->ops->construct_default_request(
265 mDevice, templateId, request);
266}
267
268status_t Camera2Device::waitUntilDrained() {
269 static const uint32_t kSleepTime = 50000; // 50 ms
270 static const uint32_t kMaxSleepTime = 10000000; // 10 s
271
272 if (mRequestQueue.getBufferCount() ==
273 CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS) return INVALID_OPERATION;
274
275 // TODO: Set up notifications from HAL, instead of sleeping here
276 uint32_t totalTime = 0;
277 while (mDevice->ops->get_in_progress_count(mDevice) > 0) {
278 usleep(kSleepTime);
279 totalTime += kSleepTime;
280 if (totalTime > kMaxSleepTime) {
281 ALOGE("%s: Waited %d us, requests still in flight", __FUNCTION__,
282 totalTime);
283 return TIMED_OUT;
284 }
285 }
286 return OK;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700287}
288
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700289/**
290 * Camera2Device::MetadataQueue
291 */
292
293Camera2Device::MetadataQueue::MetadataQueue():
294 mDevice(NULL),
295 mFrameCount(0),
296 mCount(0),
297 mStreamSlotCount(0),
298 mSignalConsumer(true)
299{
300 camera2_request_queue_src_ops::dequeue_request = consumer_dequeue;
301 camera2_request_queue_src_ops::request_count = consumer_buffer_count;
302 camera2_request_queue_src_ops::free_request = consumer_free;
303
304 camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue;
305 camera2_frame_queue_dst_ops::cancel_frame = producer_cancel;
306 camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue;
307}
308
309Camera2Device::MetadataQueue::~MetadataQueue() {
310 Mutex::Autolock l(mMutex);
311 freeBuffers(mEntries.begin(), mEntries.end());
312 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
313}
314
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700315// Connect to camera2 HAL as consumer (input requests/reprocessing)
316status_t Camera2Device::MetadataQueue::setConsumerDevice(camera2_device_t *d) {
317 status_t res;
318 res = d->ops->set_request_queue_src_ops(d,
319 this);
320 if (res != OK) return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700321 mDevice = d;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700322 return OK;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700323}
324
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700325status_t Camera2Device::MetadataQueue::setProducerDevice(camera2_device_t *d) {
326 status_t res;
327 res = d->ops->set_frame_queue_dst_ops(d,
328 this);
329 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700330}
331
332// Real interfaces
333status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) {
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700334 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700335 Mutex::Autolock l(mMutex);
336
337 mCount++;
338 mEntries.push_back(buf);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700339
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700340 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700341}
342
343int Camera2Device::MetadataQueue::getBufferCount() {
344 Mutex::Autolock l(mMutex);
345 if (mStreamSlotCount > 0) {
346 return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS;
347 }
348 return mCount;
349}
350
351status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
352 bool incrementCount)
353{
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700354 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700355 status_t res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700356 Mutex::Autolock l(mMutex);
357
358 if (mCount == 0) {
359 if (mStreamSlotCount == 0) {
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700360 ALOGVV("%s: Empty", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700361 *buf = NULL;
362 mSignalConsumer = true;
363 return OK;
364 }
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700365 ALOGVV("%s: Streaming %d frames to queue", __FUNCTION__,
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700366 mStreamSlotCount);
367
368 for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin();
369 slotEntry != mStreamSlot.end();
370 slotEntry++ ) {
371 size_t entries = get_camera_metadata_entry_count(*slotEntry);
372 size_t dataBytes = get_camera_metadata_data_count(*slotEntry);
373
374 camera_metadata_t *copy =
375 allocate_camera_metadata(entries, dataBytes);
376 append_camera_metadata(copy, *slotEntry);
377 mEntries.push_back(copy);
378 }
379 mCount = mStreamSlotCount;
380 }
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700381 ALOGVV("MetadataQueue: deque (%d buffers)", mCount);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700382 camera_metadata_t *b = *(mEntries.begin());
383 mEntries.erase(mEntries.begin());
384
385 if (incrementCount) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700386 camera_metadata_entry_t frameCount;
387 res = find_camera_metadata_entry(b,
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700388 ANDROID_REQUEST_FRAME_COUNT,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700389 &frameCount);
390 if (res != OK) {
391 ALOGE("%s: Unable to add frame count: %s (%d)",
392 __FUNCTION__, strerror(-res), res);
393 } else {
394 *frameCount.data.i32 = mFrameCount;
395 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700396 mFrameCount++;
397 }
398
399 *buf = b;
400 mCount--;
401
402 return OK;
403}
404
405status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)
406{
407 Mutex::Autolock l(mMutex);
408 status_t res;
409 while (mCount == 0) {
410 res = notEmpty.waitRelative(mMutex,timeout);
411 if (res != OK) return res;
412 }
413 return OK;
414}
415
416status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
417{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700418 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700419 Mutex::Autolock l(mMutex);
420 if (buf == NULL) {
421 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
422 mStreamSlotCount = 0;
423 return OK;
424 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700425 camera_metadata_t *buf2 = clone_camera_metadata(buf);
426 if (!buf2) {
427 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
428 return NO_MEMORY;
429 }
430
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700431 if (mStreamSlotCount > 1) {
432 List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
433 freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
434 mStreamSlotCount = 1;
435 }
436 if (mStreamSlotCount == 1) {
437 free_camera_metadata( *(mStreamSlot.begin()) );
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700438 *(mStreamSlot.begin()) = buf2;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700439 } else {
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700440 mStreamSlot.push_front(buf2);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700441 mStreamSlotCount = 1;
442 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700443 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700444}
445
446status_t Camera2Device::MetadataQueue::setStreamSlot(
447 const List<camera_metadata_t*> &bufs)
448{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700449 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700450 Mutex::Autolock l(mMutex);
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700451 status_t res;
452
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700453 if (mStreamSlotCount > 0) {
454 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
455 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700456 mStreamSlotCount = 0;
457 for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
458 r != bufs.end(); r++) {
459 camera_metadata_t *r2 = clone_camera_metadata(*r);
460 if (!r2) {
461 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
462 return NO_MEMORY;
463 }
464 mStreamSlot.push_back(r2);
465 mStreamSlotCount++;
466 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700467 return signalConsumerLocked();
468}
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700469
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700470status_t Camera2Device::MetadataQueue::dump(int fd,
471 const Vector<String16>& args) {
472 String8 result;
473 status_t notLocked;
474 notLocked = mMutex.tryLock();
475 if (notLocked) {
476 result.append(" (Unable to lock queue mutex)\n");
477 }
478 result.appendFormat(" Current frame number: %d\n", mFrameCount);
479 if (mStreamSlotCount == 0) {
480 result.append(" Stream slot: Empty\n");
481 write(fd, result.string(), result.size());
482 } else {
483 result.appendFormat(" Stream slot: %d entries\n",
484 mStreamSlot.size());
485 int i = 0;
486 for (List<camera_metadata_t*>::iterator r = mStreamSlot.begin();
487 r != mStreamSlot.end(); r++) {
488 result = String8::format(" Stream slot buffer %d:\n", i);
489 write(fd, result.string(), result.size());
490 dump_camera_metadata(*r, fd, 2);
491 i++;
492 }
493 }
494 if (mEntries.size() == 0) {
495 result = " Main queue is empty\n";
496 write(fd, result.string(), result.size());
497 } else {
498 result = String8::format(" Main queue has %d entries:\n",
499 mEntries.size());
500 int i = 0;
501 for (List<camera_metadata_t*>::iterator r = mEntries.begin();
502 r != mEntries.end(); r++) {
503 result = String8::format(" Queue entry %d:\n", i);
504 write(fd, result.string(), result.size());
505 dump_camera_metadata(*r, fd, 2);
506 i++;
507 }
508 }
509
510 if (notLocked == 0) {
511 mMutex.unlock();
512 }
513
514 return OK;
515}
516
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700517status_t Camera2Device::MetadataQueue::signalConsumerLocked() {
518 status_t res = OK;
519 notEmpty.signal();
520 if (mSignalConsumer && mDevice != NULL) {
521 mSignalConsumer = false;
522
523 mMutex.unlock();
524 ALOGV("%s: Signaling consumer", __FUNCTION__);
525 res = mDevice->ops->notify_request_queue_not_empty(mDevice);
526 mMutex.lock();
527 }
528 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700529}
530
531status_t Camera2Device::MetadataQueue::freeBuffers(
532 List<camera_metadata_t*>::iterator start,
533 List<camera_metadata_t*>::iterator end)
534{
535 while (start != end) {
536 free_camera_metadata(*start);
537 start = mStreamSlot.erase(start);
538 }
539 return OK;
540}
541
542Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
543 const camera2_request_queue_src_ops_t *q)
544{
545 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
546 return const_cast<MetadataQueue*>(cmq);
547}
548
549Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
550 const camera2_frame_queue_dst_ops_t *q)
551{
552 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
553 return const_cast<MetadataQueue*>(cmq);
554}
555
556int Camera2Device::MetadataQueue::consumer_buffer_count(
557 const camera2_request_queue_src_ops_t *q)
558{
559 MetadataQueue *queue = getInstance(q);
560 return queue->getBufferCount();
561}
562
563int Camera2Device::MetadataQueue::consumer_dequeue(
564 const camera2_request_queue_src_ops_t *q,
565 camera_metadata_t **buffer)
566{
567 MetadataQueue *queue = getInstance(q);
568 return queue->dequeue(buffer, true);
569}
570
571int Camera2Device::MetadataQueue::consumer_free(
572 const camera2_request_queue_src_ops_t *q,
573 camera_metadata_t *old_buffer)
574{
575 MetadataQueue *queue = getInstance(q);
576 free_camera_metadata(old_buffer);
577 return OK;
578}
579
580int Camera2Device::MetadataQueue::producer_dequeue(
581 const camera2_frame_queue_dst_ops_t *q,
582 size_t entries, size_t bytes,
583 camera_metadata_t **buffer)
584{
585 camera_metadata_t *new_buffer =
586 allocate_camera_metadata(entries, bytes);
587 if (new_buffer == NULL) return NO_MEMORY;
588 *buffer = new_buffer;
589 return OK;
590}
591
592int Camera2Device::MetadataQueue::producer_cancel(
593 const camera2_frame_queue_dst_ops_t *q,
594 camera_metadata_t *old_buffer)
595{
596 free_camera_metadata(old_buffer);
597 return OK;
598}
599
600int Camera2Device::MetadataQueue::producer_enqueue(
601 const camera2_frame_queue_dst_ops_t *q,
602 camera_metadata_t *filled_buffer)
603{
604 MetadataQueue *queue = getInstance(q);
605 return queue->enqueue(filled_buffer);
606}
607
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700608/**
609 * Camera2Device::StreamAdapter
610 */
611
612#ifndef container_of
613#define container_of(ptr, type, member) \
614 (type *)((char*)(ptr) - offsetof(type, member))
615#endif
616
617Camera2Device::StreamAdapter::StreamAdapter(camera2_device_t *d):
618 mState(DISCONNECTED),
619 mDevice(d),
620 mId(-1),
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700621 mWidth(0), mHeight(0), mFormat(0), mSize(0), mUsage(0),
622 mMaxProducerBuffers(0), mMaxConsumerBuffers(0),
623 mTotalBuffers(0),
624 mFormatRequested(0),
625 mActiveBuffers(0),
626 mFrameCount(0),
627 mLastTimestamp(0)
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700628{
629 camera2_stream_ops::dequeue_buffer = dequeue_buffer;
630 camera2_stream_ops::enqueue_buffer = enqueue_buffer;
631 camera2_stream_ops::cancel_buffer = cancel_buffer;
632 camera2_stream_ops::set_crop = set_crop;
633}
634
635Camera2Device::StreamAdapter::~StreamAdapter() {
636 disconnect();
637}
638
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700639status_t Camera2Device::StreamAdapter::connectToDevice(
640 sp<ANativeWindow> consumer,
641 uint32_t width, uint32_t height, int format, size_t size) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700642 status_t res;
643
644 if (mState != DISCONNECTED) return INVALID_OPERATION;
645 if (consumer == NULL) {
646 ALOGE("%s: Null consumer passed to stream adapter", __FUNCTION__);
647 return BAD_VALUE;
648 }
649
650 mConsumerInterface = consumer;
651 mWidth = width;
652 mHeight = height;
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700653 mSize = (format == HAL_PIXEL_FORMAT_BLOB) ? size : 0;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700654 mFormatRequested = format;
655
656 // Allocate device-side stream interface
657
658 uint32_t id;
659 uint32_t formatActual;
660 uint32_t usage;
661 uint32_t maxBuffers = 2;
662 res = mDevice->ops->allocate_stream(mDevice,
663 mWidth, mHeight, mFormatRequested, getStreamOps(),
664 &id, &formatActual, &usage, &maxBuffers);
665 if (res != OK) {
666 ALOGE("%s: Device stream allocation failed: %s (%d)",
667 __FUNCTION__, strerror(-res), res);
668 return res;
669 }
670
671 mId = id;
672 mFormat = formatActual;
673 mUsage = usage;
674 mMaxProducerBuffers = maxBuffers;
675
676 mState = ALLOCATED;
677
678 // Configure consumer-side ANativeWindow interface
679 res = native_window_api_connect(mConsumerInterface.get(),
680 NATIVE_WINDOW_API_CAMERA);
681 if (res != OK) {
682 ALOGE("%s: Unable to connect to native window for stream %d",
683 __FUNCTION__, mId);
684
685 return res;
686 }
687
688 mState = CONNECTED;
689
690 res = native_window_set_usage(mConsumerInterface.get(), mUsage);
691 if (res != OK) {
692 ALOGE("%s: Unable to configure usage %08x for stream %d",
693 __FUNCTION__, mUsage, mId);
694 return res;
695 }
696
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700697 res = native_window_set_scaling_mode(mConsumerInterface.get(),
698 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
699 if (res != OK) {
700 ALOGE("%s: Unable to configure stream scaling: %s (%d)",
701 __FUNCTION__, strerror(-res), res);
702 return res;
703 }
704
Eino-Ville Talvalac94cd192012-06-15 12:47:42 -0700705 res = setTransform(0);
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700706 if (res != OK) {
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700707 return res;
708 }
709
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700710 if (mFormat == HAL_PIXEL_FORMAT_BLOB) {
711 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
712 mSize, 1, mFormat);
713 if (res != OK) {
714 ALOGE("%s: Unable to configure compressed stream buffer geometry"
715 " %d x %d, size %d for stream %d",
716 __FUNCTION__, mWidth, mHeight, mSize, mId);
717 return res;
718 }
719 } else {
720 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
721 mWidth, mHeight, mFormat);
722 if (res != OK) {
723 ALOGE("%s: Unable to configure stream buffer geometry"
724 " %d x %d, format 0x%x for stream %d",
725 __FUNCTION__, mWidth, mHeight, mFormat, mId);
726 return res;
727 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700728 }
729
730 int maxConsumerBuffers;
731 res = mConsumerInterface->query(mConsumerInterface.get(),
732 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
733 if (res != OK) {
734 ALOGE("%s: Unable to query consumer undequeued"
735 " buffer count for stream %d", __FUNCTION__, mId);
736 return res;
737 }
738 mMaxConsumerBuffers = maxConsumerBuffers;
739
740 ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__,
741 mMaxProducerBuffers, mMaxConsumerBuffers);
742
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700743 mTotalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;
744 mActiveBuffers = 0;
745 mFrameCount = 0;
746 mLastTimestamp = 0;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700747
748 res = native_window_set_buffer_count(mConsumerInterface.get(),
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700749 mTotalBuffers);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700750 if (res != OK) {
751 ALOGE("%s: Unable to set buffer count for stream %d",
752 __FUNCTION__, mId);
753 return res;
754 }
755
756 // Register allocated buffers with HAL device
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700757 buffer_handle_t *buffers = new buffer_handle_t[mTotalBuffers];
758 ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[mTotalBuffers];
759 uint32_t bufferIdx = 0;
760 for (; bufferIdx < mTotalBuffers; bufferIdx++) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700761 res = mConsumerInterface->dequeueBuffer(mConsumerInterface.get(),
762 &anwBuffers[bufferIdx]);
763 if (res != OK) {
764 ALOGE("%s: Unable to dequeue buffer %d for initial registration for"
765 "stream %d", __FUNCTION__, bufferIdx, mId);
766 goto cleanUpBuffers;
767 }
768
769 res = mConsumerInterface->lockBuffer(mConsumerInterface.get(),
770 anwBuffers[bufferIdx]);
771 if (res != OK) {
772 ALOGE("%s: Unable to lock buffer %d for initial registration for"
773 "stream %d", __FUNCTION__, bufferIdx, mId);
774 bufferIdx++;
775 goto cleanUpBuffers;
776 }
777
778 buffers[bufferIdx] = anwBuffers[bufferIdx]->handle;
779 }
780
781 res = mDevice->ops->register_stream_buffers(mDevice,
782 mId,
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700783 mTotalBuffers,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700784 buffers);
785 if (res != OK) {
786 ALOGE("%s: Unable to register buffers with HAL device for stream %d",
787 __FUNCTION__, mId);
788 } else {
789 mState = ACTIVE;
790 }
791
792cleanUpBuffers:
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700793 for (uint32_t i = 0; i < bufferIdx; i++) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700794 res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
795 anwBuffers[i]);
796 if (res != OK) {
797 ALOGE("%s: Unable to cancel buffer %d after registration",
798 __FUNCTION__, i);
799 }
800 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700801 delete[] anwBuffers;
802 delete[] buffers;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700803
804 return res;
805}
806
807status_t Camera2Device::StreamAdapter::disconnect() {
808 status_t res;
809 if (mState >= ALLOCATED) {
810 res = mDevice->ops->release_stream(mDevice, mId);
811 if (res != OK) {
812 ALOGE("%s: Unable to release stream %d",
813 __FUNCTION__, mId);
814 return res;
815 }
816 }
817 if (mState >= CONNECTED) {
818 res = native_window_api_disconnect(mConsumerInterface.get(),
819 NATIVE_WINDOW_API_CAMERA);
820 if (res != OK) {
821 ALOGE("%s: Unable to disconnect stream %d from native window",
822 __FUNCTION__, mId);
823 return res;
824 }
825 }
826 mId = -1;
827 mState = DISCONNECTED;
828 return OK;
829}
830
Eino-Ville Talvalac94cd192012-06-15 12:47:42 -0700831status_t Camera2Device::StreamAdapter::setTransform(int transform) {
832 status_t res;
833 if (mState < CONNECTED) {
834 ALOGE("%s: Cannot set transform on unconnected stream", __FUNCTION__);
835 return INVALID_OPERATION;
836 }
837 res = native_window_set_buffers_transform(mConsumerInterface.get(),
838 transform);
839 if (res != OK) {
840 ALOGE("%s: Unable to configure stream transform to %x: %s (%d)",
841 __FUNCTION__, transform, strerror(-res), res);
842 }
843 return res;
844}
845
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700846status_t Camera2Device::StreamAdapter::dump(int fd,
847 const Vector<String16>& args) {
848 String8 result = String8::format(" Stream %d: %d x %d, format 0x%x\n",
849 mId, mWidth, mHeight, mFormat);
850 result.appendFormat(" size %d, usage 0x%x, requested format 0x%x\n",
851 mSize, mUsage, mFormatRequested);
852 result.appendFormat(" total buffers: %d, dequeued buffers: %d\n",
853 mTotalBuffers, mActiveBuffers);
854 result.appendFormat(" frame count: %d, last timestamp %lld\n",
855 mFrameCount, mLastTimestamp);
856 write(fd, result.string(), result.size());
857 return OK;
858}
859
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700860const camera2_stream_ops *Camera2Device::StreamAdapter::getStreamOps() {
861 return static_cast<camera2_stream_ops *>(this);
862}
863
864ANativeWindow* Camera2Device::StreamAdapter::toANW(
865 const camera2_stream_ops_t *w) {
866 return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get();
867}
868
869int Camera2Device::StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w,
870 buffer_handle_t** buffer) {
871 int res;
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700872 StreamAdapter* stream =
873 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
874 if (stream->mState != ACTIVE) {
875 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700876 return INVALID_OPERATION;
877 }
878
879 ANativeWindow *a = toANW(w);
880 ANativeWindowBuffer* anb;
881 res = a->dequeueBuffer(a, &anb);
882 if (res != OK) return res;
883 res = a->lockBuffer(a, anb);
884 if (res != OK) return res;
885
886 *buffer = &(anb->handle);
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700887 stream->mActiveBuffers++;
888
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700889 ALOGVV("%s: Buffer %p", __FUNCTION__, *buffer);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700890 return res;
891}
892
893int Camera2Device::StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w,
894 int64_t timestamp,
895 buffer_handle_t* buffer) {
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700896 StreamAdapter *stream =
897 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700898 ALOGVV("%s: Stream %d: Buffer %p captured at %lld ns",
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700899 __FUNCTION__, stream->mId, buffer, timestamp);
900 int state = stream->mState;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700901 if (state != ACTIVE) {
902 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
903 return INVALID_OPERATION;
904 }
905 ANativeWindow *a = toANW(w);
906 status_t err;
907 err = native_window_set_buffers_timestamp(a, timestamp);
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700908 if (err != OK) {
909 ALOGE("%s: Error setting timestamp on native window: %s (%d)",
910 __FUNCTION__, strerror(-err), err);
911 return err;
912 }
913 err = a->queueBuffer(a,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700914 container_of(buffer, ANativeWindowBuffer, handle));
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700915 if (err != OK) {
916 ALOGE("%s: Error queueing buffer to native window: %s (%d)",
917 __FUNCTION__, strerror(-err), err);
918 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700919 stream->mActiveBuffers--;
920 stream->mFrameCount++;
921 stream->mLastTimestamp = timestamp;
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700922 return err;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700923}
924
925int Camera2Device::StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w,
926 buffer_handle_t* buffer) {
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700927 StreamAdapter *stream =
928 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
929 if (stream->mState != ACTIVE) {
930 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700931 return INVALID_OPERATION;
932 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700933 stream->mActiveBuffers--;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700934 ANativeWindow *a = toANW(w);
935 return a->cancelBuffer(a,
936 container_of(buffer, ANativeWindowBuffer, handle));
937}
938
939int Camera2Device::StreamAdapter::set_crop(const camera2_stream_ops_t* w,
940 int left, int top, int right, int bottom) {
941 int state = static_cast<const StreamAdapter*>(w)->mState;
942 if (state != ACTIVE) {
943 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
944 return INVALID_OPERATION;
945 }
946 ANativeWindow *a = toANW(w);
947 android_native_rect_t crop = { left, top, right, bottom };
948 return native_window_set_crop(a, &crop);
949}
950
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700951
952}; // namespace android