blob: 08e3cc0f3c78051eba8fbeb8bfe9a9bf9cd1d531 [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
19
20#include <utils/Log.h>
21#include "Camera2Device.h"
22
23namespace android {
24
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070025Camera2Device::Camera2Device(int id):
26 mId(id),
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070027 mDevice(NULL)
28{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070029 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070030}
31
32Camera2Device::~Camera2Device()
33{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070034 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070035 if (mDevice) {
36 status_t res;
37 res = mDevice->common.close(&mDevice->common);
38 if (res != OK) {
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070039 ALOGE("%s: Could not close camera %d: %s (%d)",
40 __FUNCTION__,
41 mId, strerror(-res), res);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070042 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070043 mDevice = NULL;
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070044 }
45}
46
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070047status_t Camera2Device::initialize(camera_module_t *module)
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070048{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070049 ALOGV("%s: E", __FUNCTION__);
50
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070051 status_t res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070052 char name[10];
53 snprintf(name, sizeof(name), "%d", mId);
54
55 res = module->common.methods->open(&module->common, name,
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070056 reinterpret_cast<hw_device_t**>(&mDevice));
57
58 if (res != OK) {
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070059 ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
60 mId, strerror(-res), res);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070061 return res;
62 }
63
64 if (mDevice->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070065 ALOGE("%s: Could not open camera %d: "
66 "Camera device is not version %x, reports %x instead",
67 __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_2_0,
68 mDevice->common.version);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070069 return BAD_VALUE;
70 }
71
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070072 camera_info info;
73 res = module->get_camera_info(mId, &info);
74 if (res != OK ) return res;
75
76 if (info.device_version != mDevice->common.version) {
77 ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
78 " and device version (%x).", __FUNCTION__,
79 mDevice->common.version, info.device_version);
80 return BAD_VALUE;
81 }
82
83 mDeviceInfo = info.static_camera_characteristics;
84
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070085 res = mRequestQueue.setConsumerDevice(mDevice);
86 if (res != OK) {
87 ALOGE("%s: Camera %d: Unable to connect request queue to device: %s (%d)",
88 __FUNCTION__, mId, strerror(-res), res);
89 return res;
90 }
91 res = mFrameQueue.setProducerDevice(mDevice);
92 if (res != OK) {
93 ALOGE("%s: Camera %d: Unable to connect frame queue to device: %s (%d)",
94 __FUNCTION__, mId, strerror(-res), res);
95 return res;
96 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070097
98 res = mDevice->ops->get_metadata_vendor_tag_ops(mDevice, &mVendorTagOps);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070099 if (res != OK ) {
100 ALOGE("%s: Camera %d: Unable to retrieve tag ops from device: %s (%d)",
101 __FUNCTION__, mId, strerror(-res), res);
102 return res;
103 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700104
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700105 return OK;
106}
107
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700108status_t Camera2Device::dump(int fd, const Vector<String16>& args) {
109
110 String8 result;
111
112 result.appendFormat(" Camera2Device[%d] dump:\n", mId);
113
114 result.appendFormat(" Static camera information metadata:\n");
115 write(fd, result.string(), result.size());
116 dump_camera_metadata(mDeviceInfo, fd, 2);
117
118 result = " Request queue contents:\n";
119 write(fd, result.string(), result.size());
120 mRequestQueue.dump(fd, args);
121
122 result = " Frame queue contents:\n";
123 write(fd, result.string(), result.size());
124 mFrameQueue.dump(fd, args);
125
126 result = " Active streams:\n";
127 write(fd, result.string(), result.size());
128 for (StreamList::iterator s = mStreams.begin(); s != mStreams.end(); s++) {
129 (*s)->dump(fd, args);
130 }
131
132 result = " HAL device dump:\n";
133 write(fd, result.string(), result.size());
134
135 status_t res;
136 res = mDevice->ops->dump(mDevice, fd);
137
138 return res;
139}
140
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700141camera_metadata_t *Camera2Device::info() {
142 ALOGV("%s: E", __FUNCTION__);
143
144 return mDeviceInfo;
145}
146
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700147status_t Camera2Device::capture(camera_metadata_t* request) {
148 ALOGV("%s: E", __FUNCTION__);
149
150 mRequestQueue.enqueue(request);
151 return OK;
152}
153
154
155status_t Camera2Device::setStreamingRequest(camera_metadata_t* request) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700156 ALOGV("%s: E", __FUNCTION__);
157
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700158 mRequestQueue.setStreamSlot(request);
159 return OK;
160}
161
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700162status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700163 uint32_t width, uint32_t height, int format, size_t size, int *id) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700164 status_t res;
165 ALOGV("%s: E", __FUNCTION__);
166
167 sp<StreamAdapter> stream = new StreamAdapter(mDevice);
168
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700169 res = stream->connectToDevice(consumer, width, height, format, size);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700170 if (res != OK) {
171 ALOGE("%s: Camera %d: Unable to create stream (%d x %d, format %x):"
172 "%s (%d)",
173 __FUNCTION__, mId, width, height, format, strerror(-res), res);
174 return res;
175 }
176
177 *id = stream->getId();
178
179 mStreams.push_back(stream);
180 return OK;
181}
182
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700183status_t Camera2Device::getStreamInfo(int id,
184 uint32_t *width, uint32_t *height, uint32_t *format) {
185 ALOGV("%s: E", __FUNCTION__);
186 bool found = false;
187 StreamList::iterator streamI;
188 for (streamI = mStreams.begin();
189 streamI != mStreams.end(); streamI++) {
190 if ((*streamI)->getId() == id) {
191 found = true;
192 break;
193 }
194 }
195 if (!found) {
196 ALOGE("%s: Camera %d: Stream %d does not exist",
197 __FUNCTION__, mId, id);
198 return BAD_VALUE;
199 }
200
201 if (width) *width = (*streamI)->getWidth();
202 if (height) *height = (*streamI)->getHeight();
203 if (format) *format = (*streamI)->getFormat();
204
205 return OK;
206}
207
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700208status_t Camera2Device::deleteStream(int id) {
209 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700210 bool found = false;
211 for (StreamList::iterator streamI = mStreams.begin();
212 streamI != mStreams.end(); streamI++) {
213 if ((*streamI)->getId() == id) {
Eino-Ville Talvala4ecfec32012-06-12 17:13:48 -0700214 status_t res = (*streamI)->disconnect();
215 if (res != OK) {
216 ALOGE("%s: Unable to disconnect stream %d from HAL device: "
217 "%s (%d)", __FUNCTION__, id, strerror(-res), res);
218 return res;
219 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700220 mStreams.erase(streamI);
221 found = true;
222 break;
223 }
224 }
225 if (!found) {
226 ALOGE("%s: Camera %d: Unable to find stream %d to delete",
227 __FUNCTION__, mId, id);
228 return BAD_VALUE;
229 }
230 return OK;
231}
232
233status_t Camera2Device::createDefaultRequest(int templateId,
234 camera_metadata_t **request) {
235 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700236 return mDevice->ops->construct_default_request(
237 mDevice, templateId, request);
238}
239
240status_t Camera2Device::waitUntilDrained() {
241 static const uint32_t kSleepTime = 50000; // 50 ms
242 static const uint32_t kMaxSleepTime = 10000000; // 10 s
243
244 if (mRequestQueue.getBufferCount() ==
245 CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS) return INVALID_OPERATION;
246
247 // TODO: Set up notifications from HAL, instead of sleeping here
248 uint32_t totalTime = 0;
249 while (mDevice->ops->get_in_progress_count(mDevice) > 0) {
250 usleep(kSleepTime);
251 totalTime += kSleepTime;
252 if (totalTime > kMaxSleepTime) {
253 ALOGE("%s: Waited %d us, requests still in flight", __FUNCTION__,
254 totalTime);
255 return TIMED_OUT;
256 }
257 }
258 return OK;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700259}
260
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700261/**
262 * Camera2Device::MetadataQueue
263 */
264
265Camera2Device::MetadataQueue::MetadataQueue():
266 mDevice(NULL),
267 mFrameCount(0),
268 mCount(0),
269 mStreamSlotCount(0),
270 mSignalConsumer(true)
271{
272 camera2_request_queue_src_ops::dequeue_request = consumer_dequeue;
273 camera2_request_queue_src_ops::request_count = consumer_buffer_count;
274 camera2_request_queue_src_ops::free_request = consumer_free;
275
276 camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue;
277 camera2_frame_queue_dst_ops::cancel_frame = producer_cancel;
278 camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue;
279}
280
281Camera2Device::MetadataQueue::~MetadataQueue() {
282 Mutex::Autolock l(mMutex);
283 freeBuffers(mEntries.begin(), mEntries.end());
284 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
285}
286
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700287// Connect to camera2 HAL as consumer (input requests/reprocessing)
288status_t Camera2Device::MetadataQueue::setConsumerDevice(camera2_device_t *d) {
289 status_t res;
290 res = d->ops->set_request_queue_src_ops(d,
291 this);
292 if (res != OK) return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700293 mDevice = d;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700294 return OK;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700295}
296
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700297status_t Camera2Device::MetadataQueue::setProducerDevice(camera2_device_t *d) {
298 status_t res;
299 res = d->ops->set_frame_queue_dst_ops(d,
300 this);
301 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700302}
303
304// Real interfaces
305status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700306 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700307 Mutex::Autolock l(mMutex);
308
309 mCount++;
310 mEntries.push_back(buf);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700311
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700312 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700313}
314
315int Camera2Device::MetadataQueue::getBufferCount() {
316 Mutex::Autolock l(mMutex);
317 if (mStreamSlotCount > 0) {
318 return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS;
319 }
320 return mCount;
321}
322
323status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
324 bool incrementCount)
325{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700326 ALOGV("%s: E", __FUNCTION__);
327 status_t res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700328 Mutex::Autolock l(mMutex);
329
330 if (mCount == 0) {
331 if (mStreamSlotCount == 0) {
332 ALOGV("%s: Empty", __FUNCTION__);
333 *buf = NULL;
334 mSignalConsumer = true;
335 return OK;
336 }
337 ALOGV("%s: Streaming %d frames to queue", __FUNCTION__,
338 mStreamSlotCount);
339
340 for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin();
341 slotEntry != mStreamSlot.end();
342 slotEntry++ ) {
343 size_t entries = get_camera_metadata_entry_count(*slotEntry);
344 size_t dataBytes = get_camera_metadata_data_count(*slotEntry);
345
346 camera_metadata_t *copy =
347 allocate_camera_metadata(entries, dataBytes);
348 append_camera_metadata(copy, *slotEntry);
349 mEntries.push_back(copy);
350 }
351 mCount = mStreamSlotCount;
352 }
353 ALOGV("MetadataQueue: deque (%d buffers)", mCount);
354 camera_metadata_t *b = *(mEntries.begin());
355 mEntries.erase(mEntries.begin());
356
357 if (incrementCount) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700358 camera_metadata_entry_t frameCount;
359 res = find_camera_metadata_entry(b,
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700360 ANDROID_REQUEST_FRAME_COUNT,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700361 &frameCount);
362 if (res != OK) {
363 ALOGE("%s: Unable to add frame count: %s (%d)",
364 __FUNCTION__, strerror(-res), res);
365 } else {
366 *frameCount.data.i32 = mFrameCount;
367 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700368 mFrameCount++;
369 }
370
371 *buf = b;
372 mCount--;
373
374 return OK;
375}
376
377status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)
378{
379 Mutex::Autolock l(mMutex);
380 status_t res;
381 while (mCount == 0) {
382 res = notEmpty.waitRelative(mMutex,timeout);
383 if (res != OK) return res;
384 }
385 return OK;
386}
387
388status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
389{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700390 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700391 Mutex::Autolock l(mMutex);
392 if (buf == NULL) {
393 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
394 mStreamSlotCount = 0;
395 return OK;
396 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700397 camera_metadata_t *buf2 = clone_camera_metadata(buf);
398 if (!buf2) {
399 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
400 return NO_MEMORY;
401 }
402
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700403 if (mStreamSlotCount > 1) {
404 List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
405 freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
406 mStreamSlotCount = 1;
407 }
408 if (mStreamSlotCount == 1) {
409 free_camera_metadata( *(mStreamSlot.begin()) );
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700410 *(mStreamSlot.begin()) = buf2;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700411 } else {
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700412 mStreamSlot.push_front(buf2);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700413 mStreamSlotCount = 1;
414 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700415 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700416}
417
418status_t Camera2Device::MetadataQueue::setStreamSlot(
419 const List<camera_metadata_t*> &bufs)
420{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700421 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700422 Mutex::Autolock l(mMutex);
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700423 status_t res;
424
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700425 if (mStreamSlotCount > 0) {
426 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
427 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700428 mStreamSlotCount = 0;
429 for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
430 r != bufs.end(); r++) {
431 camera_metadata_t *r2 = clone_camera_metadata(*r);
432 if (!r2) {
433 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
434 return NO_MEMORY;
435 }
436 mStreamSlot.push_back(r2);
437 mStreamSlotCount++;
438 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700439 return signalConsumerLocked();
440}
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700441
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700442status_t Camera2Device::MetadataQueue::dump(int fd,
443 const Vector<String16>& args) {
444 String8 result;
445 status_t notLocked;
446 notLocked = mMutex.tryLock();
447 if (notLocked) {
448 result.append(" (Unable to lock queue mutex)\n");
449 }
450 result.appendFormat(" Current frame number: %d\n", mFrameCount);
451 if (mStreamSlotCount == 0) {
452 result.append(" Stream slot: Empty\n");
453 write(fd, result.string(), result.size());
454 } else {
455 result.appendFormat(" Stream slot: %d entries\n",
456 mStreamSlot.size());
457 int i = 0;
458 for (List<camera_metadata_t*>::iterator r = mStreamSlot.begin();
459 r != mStreamSlot.end(); r++) {
460 result = String8::format(" Stream slot buffer %d:\n", i);
461 write(fd, result.string(), result.size());
462 dump_camera_metadata(*r, fd, 2);
463 i++;
464 }
465 }
466 if (mEntries.size() == 0) {
467 result = " Main queue is empty\n";
468 write(fd, result.string(), result.size());
469 } else {
470 result = String8::format(" Main queue has %d entries:\n",
471 mEntries.size());
472 int i = 0;
473 for (List<camera_metadata_t*>::iterator r = mEntries.begin();
474 r != mEntries.end(); r++) {
475 result = String8::format(" Queue entry %d:\n", i);
476 write(fd, result.string(), result.size());
477 dump_camera_metadata(*r, fd, 2);
478 i++;
479 }
480 }
481
482 if (notLocked == 0) {
483 mMutex.unlock();
484 }
485
486 return OK;
487}
488
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700489status_t Camera2Device::MetadataQueue::signalConsumerLocked() {
490 status_t res = OK;
491 notEmpty.signal();
492 if (mSignalConsumer && mDevice != NULL) {
493 mSignalConsumer = false;
494
495 mMutex.unlock();
496 ALOGV("%s: Signaling consumer", __FUNCTION__);
497 res = mDevice->ops->notify_request_queue_not_empty(mDevice);
498 mMutex.lock();
499 }
500 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700501}
502
503status_t Camera2Device::MetadataQueue::freeBuffers(
504 List<camera_metadata_t*>::iterator start,
505 List<camera_metadata_t*>::iterator end)
506{
507 while (start != end) {
508 free_camera_metadata(*start);
509 start = mStreamSlot.erase(start);
510 }
511 return OK;
512}
513
514Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
515 const camera2_request_queue_src_ops_t *q)
516{
517 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
518 return const_cast<MetadataQueue*>(cmq);
519}
520
521Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
522 const camera2_frame_queue_dst_ops_t *q)
523{
524 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
525 return const_cast<MetadataQueue*>(cmq);
526}
527
528int Camera2Device::MetadataQueue::consumer_buffer_count(
529 const camera2_request_queue_src_ops_t *q)
530{
531 MetadataQueue *queue = getInstance(q);
532 return queue->getBufferCount();
533}
534
535int Camera2Device::MetadataQueue::consumer_dequeue(
536 const camera2_request_queue_src_ops_t *q,
537 camera_metadata_t **buffer)
538{
539 MetadataQueue *queue = getInstance(q);
540 return queue->dequeue(buffer, true);
541}
542
543int Camera2Device::MetadataQueue::consumer_free(
544 const camera2_request_queue_src_ops_t *q,
545 camera_metadata_t *old_buffer)
546{
547 MetadataQueue *queue = getInstance(q);
548 free_camera_metadata(old_buffer);
549 return OK;
550}
551
552int Camera2Device::MetadataQueue::producer_dequeue(
553 const camera2_frame_queue_dst_ops_t *q,
554 size_t entries, size_t bytes,
555 camera_metadata_t **buffer)
556{
557 camera_metadata_t *new_buffer =
558 allocate_camera_metadata(entries, bytes);
559 if (new_buffer == NULL) return NO_MEMORY;
560 *buffer = new_buffer;
561 return OK;
562}
563
564int Camera2Device::MetadataQueue::producer_cancel(
565 const camera2_frame_queue_dst_ops_t *q,
566 camera_metadata_t *old_buffer)
567{
568 free_camera_metadata(old_buffer);
569 return OK;
570}
571
572int Camera2Device::MetadataQueue::producer_enqueue(
573 const camera2_frame_queue_dst_ops_t *q,
574 camera_metadata_t *filled_buffer)
575{
576 MetadataQueue *queue = getInstance(q);
577 return queue->enqueue(filled_buffer);
578}
579
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700580/**
581 * Camera2Device::StreamAdapter
582 */
583
584#ifndef container_of
585#define container_of(ptr, type, member) \
586 (type *)((char*)(ptr) - offsetof(type, member))
587#endif
588
589Camera2Device::StreamAdapter::StreamAdapter(camera2_device_t *d):
590 mState(DISCONNECTED),
591 mDevice(d),
592 mId(-1),
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700593 mWidth(0), mHeight(0), mFormat(0), mSize(0), mUsage(0),
594 mMaxProducerBuffers(0), mMaxConsumerBuffers(0),
595 mTotalBuffers(0),
596 mFormatRequested(0),
597 mActiveBuffers(0),
598 mFrameCount(0),
599 mLastTimestamp(0)
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700600{
601 camera2_stream_ops::dequeue_buffer = dequeue_buffer;
602 camera2_stream_ops::enqueue_buffer = enqueue_buffer;
603 camera2_stream_ops::cancel_buffer = cancel_buffer;
604 camera2_stream_ops::set_crop = set_crop;
605}
606
607Camera2Device::StreamAdapter::~StreamAdapter() {
608 disconnect();
609}
610
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700611status_t Camera2Device::StreamAdapter::connectToDevice(
612 sp<ANativeWindow> consumer,
613 uint32_t width, uint32_t height, int format, size_t size) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700614 status_t res;
615
616 if (mState != DISCONNECTED) return INVALID_OPERATION;
617 if (consumer == NULL) {
618 ALOGE("%s: Null consumer passed to stream adapter", __FUNCTION__);
619 return BAD_VALUE;
620 }
621
622 mConsumerInterface = consumer;
623 mWidth = width;
624 mHeight = height;
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700625 mSize = (format == HAL_PIXEL_FORMAT_BLOB) ? size : 0;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700626 mFormatRequested = format;
627
628 // Allocate device-side stream interface
629
630 uint32_t id;
631 uint32_t formatActual;
632 uint32_t usage;
633 uint32_t maxBuffers = 2;
634 res = mDevice->ops->allocate_stream(mDevice,
635 mWidth, mHeight, mFormatRequested, getStreamOps(),
636 &id, &formatActual, &usage, &maxBuffers);
637 if (res != OK) {
638 ALOGE("%s: Device stream allocation failed: %s (%d)",
639 __FUNCTION__, strerror(-res), res);
640 return res;
641 }
642
643 mId = id;
644 mFormat = formatActual;
645 mUsage = usage;
646 mMaxProducerBuffers = maxBuffers;
647
648 mState = ALLOCATED;
649
650 // Configure consumer-side ANativeWindow interface
651 res = native_window_api_connect(mConsumerInterface.get(),
652 NATIVE_WINDOW_API_CAMERA);
653 if (res != OK) {
654 ALOGE("%s: Unable to connect to native window for stream %d",
655 __FUNCTION__, mId);
656
657 return res;
658 }
659
660 mState = CONNECTED;
661
662 res = native_window_set_usage(mConsumerInterface.get(), mUsage);
663 if (res != OK) {
664 ALOGE("%s: Unable to configure usage %08x for stream %d",
665 __FUNCTION__, mUsage, mId);
666 return res;
667 }
668
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700669 res = native_window_set_scaling_mode(mConsumerInterface.get(),
670 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
671 if (res != OK) {
672 ALOGE("%s: Unable to configure stream scaling: %s (%d)",
673 __FUNCTION__, strerror(-res), res);
674 return res;
675 }
676
677 res = native_window_set_buffers_transform(mConsumerInterface.get(), 0);
678 if (res != OK) {
679 ALOGE("%s: Unable to configure stream transform: %s (%d)",
680 __FUNCTION__, strerror(-res), res);
681 return res;
682 }
683
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700684 if (mFormat == HAL_PIXEL_FORMAT_BLOB) {
685 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
686 mSize, 1, mFormat);
687 if (res != OK) {
688 ALOGE("%s: Unable to configure compressed stream buffer geometry"
689 " %d x %d, size %d for stream %d",
690 __FUNCTION__, mWidth, mHeight, mSize, mId);
691 return res;
692 }
693 } else {
694 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
695 mWidth, mHeight, mFormat);
696 if (res != OK) {
697 ALOGE("%s: Unable to configure stream buffer geometry"
698 " %d x %d, format 0x%x for stream %d",
699 __FUNCTION__, mWidth, mHeight, mFormat, mId);
700 return res;
701 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700702 }
703
704 int maxConsumerBuffers;
705 res = mConsumerInterface->query(mConsumerInterface.get(),
706 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
707 if (res != OK) {
708 ALOGE("%s: Unable to query consumer undequeued"
709 " buffer count for stream %d", __FUNCTION__, mId);
710 return res;
711 }
712 mMaxConsumerBuffers = maxConsumerBuffers;
713
714 ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__,
715 mMaxProducerBuffers, mMaxConsumerBuffers);
716
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700717 mTotalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;
718 mActiveBuffers = 0;
719 mFrameCount = 0;
720 mLastTimestamp = 0;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700721
722 res = native_window_set_buffer_count(mConsumerInterface.get(),
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700723 mTotalBuffers);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700724 if (res != OK) {
725 ALOGE("%s: Unable to set buffer count for stream %d",
726 __FUNCTION__, mId);
727 return res;
728 }
729
730 // Register allocated buffers with HAL device
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700731 buffer_handle_t *buffers = new buffer_handle_t[mTotalBuffers];
732 ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[mTotalBuffers];
733 uint32_t bufferIdx = 0;
734 for (; bufferIdx < mTotalBuffers; bufferIdx++) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700735 res = mConsumerInterface->dequeueBuffer(mConsumerInterface.get(),
736 &anwBuffers[bufferIdx]);
737 if (res != OK) {
738 ALOGE("%s: Unable to dequeue buffer %d for initial registration for"
739 "stream %d", __FUNCTION__, bufferIdx, mId);
740 goto cleanUpBuffers;
741 }
742
743 res = mConsumerInterface->lockBuffer(mConsumerInterface.get(),
744 anwBuffers[bufferIdx]);
745 if (res != OK) {
746 ALOGE("%s: Unable to lock buffer %d for initial registration for"
747 "stream %d", __FUNCTION__, bufferIdx, mId);
748 bufferIdx++;
749 goto cleanUpBuffers;
750 }
751
752 buffers[bufferIdx] = anwBuffers[bufferIdx]->handle;
753 }
754
755 res = mDevice->ops->register_stream_buffers(mDevice,
756 mId,
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700757 mTotalBuffers,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700758 buffers);
759 if (res != OK) {
760 ALOGE("%s: Unable to register buffers with HAL device for stream %d",
761 __FUNCTION__, mId);
762 } else {
763 mState = ACTIVE;
764 }
765
766cleanUpBuffers:
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700767 for (uint32_t i = 0; i < bufferIdx; i++) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700768 res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
769 anwBuffers[i]);
770 if (res != OK) {
771 ALOGE("%s: Unable to cancel buffer %d after registration",
772 __FUNCTION__, i);
773 }
774 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700775 delete[] anwBuffers;
776 delete[] buffers;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700777
778 return res;
779}
780
781status_t Camera2Device::StreamAdapter::disconnect() {
782 status_t res;
783 if (mState >= ALLOCATED) {
784 res = mDevice->ops->release_stream(mDevice, mId);
785 if (res != OK) {
786 ALOGE("%s: Unable to release stream %d",
787 __FUNCTION__, mId);
788 return res;
789 }
790 }
791 if (mState >= CONNECTED) {
792 res = native_window_api_disconnect(mConsumerInterface.get(),
793 NATIVE_WINDOW_API_CAMERA);
794 if (res != OK) {
795 ALOGE("%s: Unable to disconnect stream %d from native window",
796 __FUNCTION__, mId);
797 return res;
798 }
799 }
800 mId = -1;
801 mState = DISCONNECTED;
802 return OK;
803}
804
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700805status_t Camera2Device::StreamAdapter::dump(int fd,
806 const Vector<String16>& args) {
807 String8 result = String8::format(" Stream %d: %d x %d, format 0x%x\n",
808 mId, mWidth, mHeight, mFormat);
809 result.appendFormat(" size %d, usage 0x%x, requested format 0x%x\n",
810 mSize, mUsage, mFormatRequested);
811 result.appendFormat(" total buffers: %d, dequeued buffers: %d\n",
812 mTotalBuffers, mActiveBuffers);
813 result.appendFormat(" frame count: %d, last timestamp %lld\n",
814 mFrameCount, mLastTimestamp);
815 write(fd, result.string(), result.size());
816 return OK;
817}
818
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700819const camera2_stream_ops *Camera2Device::StreamAdapter::getStreamOps() {
820 return static_cast<camera2_stream_ops *>(this);
821}
822
823ANativeWindow* Camera2Device::StreamAdapter::toANW(
824 const camera2_stream_ops_t *w) {
825 return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get();
826}
827
828int Camera2Device::StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w,
829 buffer_handle_t** buffer) {
830 int res;
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700831 StreamAdapter* stream =
832 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
833 if (stream->mState != ACTIVE) {
834 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700835 return INVALID_OPERATION;
836 }
837
838 ANativeWindow *a = toANW(w);
839 ANativeWindowBuffer* anb;
840 res = a->dequeueBuffer(a, &anb);
841 if (res != OK) return res;
842 res = a->lockBuffer(a, anb);
843 if (res != OK) return res;
844
845 *buffer = &(anb->handle);
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700846 stream->mActiveBuffers++;
847
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700848 ALOGV("%s: Buffer %p", __FUNCTION__, *buffer);
849 return res;
850}
851
852int Camera2Device::StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w,
853 int64_t timestamp,
854 buffer_handle_t* buffer) {
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700855 StreamAdapter *stream =
856 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700857 ALOGV("%s: Stream %d: Buffer %p captured at %lld ns",
858 __FUNCTION__, stream->mId, buffer, timestamp);
859 int state = stream->mState;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700860 if (state != ACTIVE) {
861 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
862 return INVALID_OPERATION;
863 }
864 ANativeWindow *a = toANW(w);
865 status_t err;
866 err = native_window_set_buffers_timestamp(a, timestamp);
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700867 if (err != OK) {
868 ALOGE("%s: Error setting timestamp on native window: %s (%d)",
869 __FUNCTION__, strerror(-err), err);
870 return err;
871 }
872 err = a->queueBuffer(a,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700873 container_of(buffer, ANativeWindowBuffer, handle));
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700874 if (err != OK) {
875 ALOGE("%s: Error queueing buffer to native window: %s (%d)",
876 __FUNCTION__, strerror(-err), err);
877 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700878 stream->mActiveBuffers--;
879 stream->mFrameCount++;
880 stream->mLastTimestamp = timestamp;
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700881 return err;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700882}
883
884int Camera2Device::StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w,
885 buffer_handle_t* buffer) {
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700886 StreamAdapter *stream =
887 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
888 if (stream->mState != ACTIVE) {
889 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700890 return INVALID_OPERATION;
891 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700892 stream->mActiveBuffers--;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700893 ANativeWindow *a = toANW(w);
894 return a->cancelBuffer(a,
895 container_of(buffer, ANativeWindowBuffer, handle));
896}
897
898int Camera2Device::StreamAdapter::set_crop(const camera2_stream_ops_t* w,
899 int left, int top, int right, int bottom) {
900 int state = static_cast<const StreamAdapter*>(w)->mState;
901 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 android_native_rect_t crop = { left, top, right, bottom };
907 return native_window_set_crop(a, &crop);
908}
909
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700910
911}; // namespace android