blob: 476126310242b4c7f906b5747b6a764045a1da3c [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 Talvalac94cd192012-06-15 12:47:42 -0700208status_t Camera2Device::setStreamTransform(int id,
209 int transform) {
210 ALOGV("%s: E", __FUNCTION__);
211 bool found = false;
212 StreamList::iterator streamI;
213 for (streamI = mStreams.begin();
214 streamI != mStreams.end(); streamI++) {
215 if ((*streamI)->getId() == id) {
216 found = true;
217 break;
218 }
219 }
220 if (!found) {
221 ALOGE("%s: Camera %d: Stream %d does not exist",
222 __FUNCTION__, mId, id);
223 return BAD_VALUE;
224 }
225
226 return (*streamI)->setTransform(transform);
227}
228
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700229status_t Camera2Device::deleteStream(int id) {
230 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700231 bool found = false;
232 for (StreamList::iterator streamI = mStreams.begin();
233 streamI != mStreams.end(); streamI++) {
234 if ((*streamI)->getId() == id) {
Eino-Ville Talvala4ecfec32012-06-12 17:13:48 -0700235 status_t res = (*streamI)->disconnect();
236 if (res != OK) {
237 ALOGE("%s: Unable to disconnect stream %d from HAL device: "
238 "%s (%d)", __FUNCTION__, id, strerror(-res), res);
239 return res;
240 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700241 mStreams.erase(streamI);
242 found = true;
243 break;
244 }
245 }
246 if (!found) {
247 ALOGE("%s: Camera %d: Unable to find stream %d to delete",
248 __FUNCTION__, mId, id);
249 return BAD_VALUE;
250 }
251 return OK;
252}
253
254status_t Camera2Device::createDefaultRequest(int templateId,
255 camera_metadata_t **request) {
256 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700257 return mDevice->ops->construct_default_request(
258 mDevice, templateId, request);
259}
260
261status_t Camera2Device::waitUntilDrained() {
262 static const uint32_t kSleepTime = 50000; // 50 ms
263 static const uint32_t kMaxSleepTime = 10000000; // 10 s
264
265 if (mRequestQueue.getBufferCount() ==
266 CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS) return INVALID_OPERATION;
267
268 // TODO: Set up notifications from HAL, instead of sleeping here
269 uint32_t totalTime = 0;
270 while (mDevice->ops->get_in_progress_count(mDevice) > 0) {
271 usleep(kSleepTime);
272 totalTime += kSleepTime;
273 if (totalTime > kMaxSleepTime) {
274 ALOGE("%s: Waited %d us, requests still in flight", __FUNCTION__,
275 totalTime);
276 return TIMED_OUT;
277 }
278 }
279 return OK;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700280}
281
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700282/**
283 * Camera2Device::MetadataQueue
284 */
285
286Camera2Device::MetadataQueue::MetadataQueue():
287 mDevice(NULL),
288 mFrameCount(0),
289 mCount(0),
290 mStreamSlotCount(0),
291 mSignalConsumer(true)
292{
293 camera2_request_queue_src_ops::dequeue_request = consumer_dequeue;
294 camera2_request_queue_src_ops::request_count = consumer_buffer_count;
295 camera2_request_queue_src_ops::free_request = consumer_free;
296
297 camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue;
298 camera2_frame_queue_dst_ops::cancel_frame = producer_cancel;
299 camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue;
300}
301
302Camera2Device::MetadataQueue::~MetadataQueue() {
303 Mutex::Autolock l(mMutex);
304 freeBuffers(mEntries.begin(), mEntries.end());
305 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
306}
307
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700308// Connect to camera2 HAL as consumer (input requests/reprocessing)
309status_t Camera2Device::MetadataQueue::setConsumerDevice(camera2_device_t *d) {
310 status_t res;
311 res = d->ops->set_request_queue_src_ops(d,
312 this);
313 if (res != OK) return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700314 mDevice = d;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700315 return OK;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700316}
317
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700318status_t Camera2Device::MetadataQueue::setProducerDevice(camera2_device_t *d) {
319 status_t res;
320 res = d->ops->set_frame_queue_dst_ops(d,
321 this);
322 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700323}
324
325// Real interfaces
326status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700327 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700328 Mutex::Autolock l(mMutex);
329
330 mCount++;
331 mEntries.push_back(buf);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700332
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700333 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700334}
335
336int Camera2Device::MetadataQueue::getBufferCount() {
337 Mutex::Autolock l(mMutex);
338 if (mStreamSlotCount > 0) {
339 return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS;
340 }
341 return mCount;
342}
343
344status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
345 bool incrementCount)
346{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700347 ALOGV("%s: E", __FUNCTION__);
348 status_t res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700349 Mutex::Autolock l(mMutex);
350
351 if (mCount == 0) {
352 if (mStreamSlotCount == 0) {
353 ALOGV("%s: Empty", __FUNCTION__);
354 *buf = NULL;
355 mSignalConsumer = true;
356 return OK;
357 }
358 ALOGV("%s: Streaming %d frames to queue", __FUNCTION__,
359 mStreamSlotCount);
360
361 for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin();
362 slotEntry != mStreamSlot.end();
363 slotEntry++ ) {
364 size_t entries = get_camera_metadata_entry_count(*slotEntry);
365 size_t dataBytes = get_camera_metadata_data_count(*slotEntry);
366
367 camera_metadata_t *copy =
368 allocate_camera_metadata(entries, dataBytes);
369 append_camera_metadata(copy, *slotEntry);
370 mEntries.push_back(copy);
371 }
372 mCount = mStreamSlotCount;
373 }
374 ALOGV("MetadataQueue: deque (%d buffers)", mCount);
375 camera_metadata_t *b = *(mEntries.begin());
376 mEntries.erase(mEntries.begin());
377
378 if (incrementCount) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700379 camera_metadata_entry_t frameCount;
380 res = find_camera_metadata_entry(b,
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700381 ANDROID_REQUEST_FRAME_COUNT,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700382 &frameCount);
383 if (res != OK) {
384 ALOGE("%s: Unable to add frame count: %s (%d)",
385 __FUNCTION__, strerror(-res), res);
386 } else {
387 *frameCount.data.i32 = mFrameCount;
388 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700389 mFrameCount++;
390 }
391
392 *buf = b;
393 mCount--;
394
395 return OK;
396}
397
398status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)
399{
400 Mutex::Autolock l(mMutex);
401 status_t res;
402 while (mCount == 0) {
403 res = notEmpty.waitRelative(mMutex,timeout);
404 if (res != OK) return res;
405 }
406 return OK;
407}
408
409status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
410{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700411 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700412 Mutex::Autolock l(mMutex);
413 if (buf == NULL) {
414 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
415 mStreamSlotCount = 0;
416 return OK;
417 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700418 camera_metadata_t *buf2 = clone_camera_metadata(buf);
419 if (!buf2) {
420 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
421 return NO_MEMORY;
422 }
423
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700424 if (mStreamSlotCount > 1) {
425 List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
426 freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
427 mStreamSlotCount = 1;
428 }
429 if (mStreamSlotCount == 1) {
430 free_camera_metadata( *(mStreamSlot.begin()) );
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700431 *(mStreamSlot.begin()) = buf2;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700432 } else {
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700433 mStreamSlot.push_front(buf2);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700434 mStreamSlotCount = 1;
435 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700436 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700437}
438
439status_t Camera2Device::MetadataQueue::setStreamSlot(
440 const List<camera_metadata_t*> &bufs)
441{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700442 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700443 Mutex::Autolock l(mMutex);
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700444 status_t res;
445
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700446 if (mStreamSlotCount > 0) {
447 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
448 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700449 mStreamSlotCount = 0;
450 for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
451 r != bufs.end(); r++) {
452 camera_metadata_t *r2 = clone_camera_metadata(*r);
453 if (!r2) {
454 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
455 return NO_MEMORY;
456 }
457 mStreamSlot.push_back(r2);
458 mStreamSlotCount++;
459 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700460 return signalConsumerLocked();
461}
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700462
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700463status_t Camera2Device::MetadataQueue::dump(int fd,
464 const Vector<String16>& args) {
465 String8 result;
466 status_t notLocked;
467 notLocked = mMutex.tryLock();
468 if (notLocked) {
469 result.append(" (Unable to lock queue mutex)\n");
470 }
471 result.appendFormat(" Current frame number: %d\n", mFrameCount);
472 if (mStreamSlotCount == 0) {
473 result.append(" Stream slot: Empty\n");
474 write(fd, result.string(), result.size());
475 } else {
476 result.appendFormat(" Stream slot: %d entries\n",
477 mStreamSlot.size());
478 int i = 0;
479 for (List<camera_metadata_t*>::iterator r = mStreamSlot.begin();
480 r != mStreamSlot.end(); r++) {
481 result = String8::format(" Stream slot buffer %d:\n", i);
482 write(fd, result.string(), result.size());
483 dump_camera_metadata(*r, fd, 2);
484 i++;
485 }
486 }
487 if (mEntries.size() == 0) {
488 result = " Main queue is empty\n";
489 write(fd, result.string(), result.size());
490 } else {
491 result = String8::format(" Main queue has %d entries:\n",
492 mEntries.size());
493 int i = 0;
494 for (List<camera_metadata_t*>::iterator r = mEntries.begin();
495 r != mEntries.end(); r++) {
496 result = String8::format(" Queue entry %d:\n", i);
497 write(fd, result.string(), result.size());
498 dump_camera_metadata(*r, fd, 2);
499 i++;
500 }
501 }
502
503 if (notLocked == 0) {
504 mMutex.unlock();
505 }
506
507 return OK;
508}
509
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700510status_t Camera2Device::MetadataQueue::signalConsumerLocked() {
511 status_t res = OK;
512 notEmpty.signal();
513 if (mSignalConsumer && mDevice != NULL) {
514 mSignalConsumer = false;
515
516 mMutex.unlock();
517 ALOGV("%s: Signaling consumer", __FUNCTION__);
518 res = mDevice->ops->notify_request_queue_not_empty(mDevice);
519 mMutex.lock();
520 }
521 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700522}
523
524status_t Camera2Device::MetadataQueue::freeBuffers(
525 List<camera_metadata_t*>::iterator start,
526 List<camera_metadata_t*>::iterator end)
527{
528 while (start != end) {
529 free_camera_metadata(*start);
530 start = mStreamSlot.erase(start);
531 }
532 return OK;
533}
534
535Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
536 const camera2_request_queue_src_ops_t *q)
537{
538 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
539 return const_cast<MetadataQueue*>(cmq);
540}
541
542Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
543 const camera2_frame_queue_dst_ops_t *q)
544{
545 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
546 return const_cast<MetadataQueue*>(cmq);
547}
548
549int Camera2Device::MetadataQueue::consumer_buffer_count(
550 const camera2_request_queue_src_ops_t *q)
551{
552 MetadataQueue *queue = getInstance(q);
553 return queue->getBufferCount();
554}
555
556int Camera2Device::MetadataQueue::consumer_dequeue(
557 const camera2_request_queue_src_ops_t *q,
558 camera_metadata_t **buffer)
559{
560 MetadataQueue *queue = getInstance(q);
561 return queue->dequeue(buffer, true);
562}
563
564int Camera2Device::MetadataQueue::consumer_free(
565 const camera2_request_queue_src_ops_t *q,
566 camera_metadata_t *old_buffer)
567{
568 MetadataQueue *queue = getInstance(q);
569 free_camera_metadata(old_buffer);
570 return OK;
571}
572
573int Camera2Device::MetadataQueue::producer_dequeue(
574 const camera2_frame_queue_dst_ops_t *q,
575 size_t entries, size_t bytes,
576 camera_metadata_t **buffer)
577{
578 camera_metadata_t *new_buffer =
579 allocate_camera_metadata(entries, bytes);
580 if (new_buffer == NULL) return NO_MEMORY;
581 *buffer = new_buffer;
582 return OK;
583}
584
585int Camera2Device::MetadataQueue::producer_cancel(
586 const camera2_frame_queue_dst_ops_t *q,
587 camera_metadata_t *old_buffer)
588{
589 free_camera_metadata(old_buffer);
590 return OK;
591}
592
593int Camera2Device::MetadataQueue::producer_enqueue(
594 const camera2_frame_queue_dst_ops_t *q,
595 camera_metadata_t *filled_buffer)
596{
597 MetadataQueue *queue = getInstance(q);
598 return queue->enqueue(filled_buffer);
599}
600
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700601/**
602 * Camera2Device::StreamAdapter
603 */
604
605#ifndef container_of
606#define container_of(ptr, type, member) \
607 (type *)((char*)(ptr) - offsetof(type, member))
608#endif
609
610Camera2Device::StreamAdapter::StreamAdapter(camera2_device_t *d):
611 mState(DISCONNECTED),
612 mDevice(d),
613 mId(-1),
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700614 mWidth(0), mHeight(0), mFormat(0), mSize(0), mUsage(0),
615 mMaxProducerBuffers(0), mMaxConsumerBuffers(0),
616 mTotalBuffers(0),
617 mFormatRequested(0),
618 mActiveBuffers(0),
619 mFrameCount(0),
620 mLastTimestamp(0)
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700621{
622 camera2_stream_ops::dequeue_buffer = dequeue_buffer;
623 camera2_stream_ops::enqueue_buffer = enqueue_buffer;
624 camera2_stream_ops::cancel_buffer = cancel_buffer;
625 camera2_stream_ops::set_crop = set_crop;
626}
627
628Camera2Device::StreamAdapter::~StreamAdapter() {
629 disconnect();
630}
631
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700632status_t Camera2Device::StreamAdapter::connectToDevice(
633 sp<ANativeWindow> consumer,
634 uint32_t width, uint32_t height, int format, size_t size) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700635 status_t res;
636
637 if (mState != DISCONNECTED) return INVALID_OPERATION;
638 if (consumer == NULL) {
639 ALOGE("%s: Null consumer passed to stream adapter", __FUNCTION__);
640 return BAD_VALUE;
641 }
642
643 mConsumerInterface = consumer;
644 mWidth = width;
645 mHeight = height;
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700646 mSize = (format == HAL_PIXEL_FORMAT_BLOB) ? size : 0;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700647 mFormatRequested = format;
648
649 // Allocate device-side stream interface
650
651 uint32_t id;
652 uint32_t formatActual;
653 uint32_t usage;
654 uint32_t maxBuffers = 2;
655 res = mDevice->ops->allocate_stream(mDevice,
656 mWidth, mHeight, mFormatRequested, getStreamOps(),
657 &id, &formatActual, &usage, &maxBuffers);
658 if (res != OK) {
659 ALOGE("%s: Device stream allocation failed: %s (%d)",
660 __FUNCTION__, strerror(-res), res);
661 return res;
662 }
663
664 mId = id;
665 mFormat = formatActual;
666 mUsage = usage;
667 mMaxProducerBuffers = maxBuffers;
668
669 mState = ALLOCATED;
670
671 // Configure consumer-side ANativeWindow interface
672 res = native_window_api_connect(mConsumerInterface.get(),
673 NATIVE_WINDOW_API_CAMERA);
674 if (res != OK) {
675 ALOGE("%s: Unable to connect to native window for stream %d",
676 __FUNCTION__, mId);
677
678 return res;
679 }
680
681 mState = CONNECTED;
682
683 res = native_window_set_usage(mConsumerInterface.get(), mUsage);
684 if (res != OK) {
685 ALOGE("%s: Unable to configure usage %08x for stream %d",
686 __FUNCTION__, mUsage, mId);
687 return res;
688 }
689
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700690 res = native_window_set_scaling_mode(mConsumerInterface.get(),
691 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
692 if (res != OK) {
693 ALOGE("%s: Unable to configure stream scaling: %s (%d)",
694 __FUNCTION__, strerror(-res), res);
695 return res;
696 }
697
Eino-Ville Talvalac94cd192012-06-15 12:47:42 -0700698 res = setTransform(0);
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700699 if (res != OK) {
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700700 return res;
701 }
702
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700703 if (mFormat == HAL_PIXEL_FORMAT_BLOB) {
704 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
705 mSize, 1, mFormat);
706 if (res != OK) {
707 ALOGE("%s: Unable to configure compressed stream buffer geometry"
708 " %d x %d, size %d for stream %d",
709 __FUNCTION__, mWidth, mHeight, mSize, mId);
710 return res;
711 }
712 } else {
713 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
714 mWidth, mHeight, mFormat);
715 if (res != OK) {
716 ALOGE("%s: Unable to configure stream buffer geometry"
717 " %d x %d, format 0x%x for stream %d",
718 __FUNCTION__, mWidth, mHeight, mFormat, mId);
719 return res;
720 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700721 }
722
723 int maxConsumerBuffers;
724 res = mConsumerInterface->query(mConsumerInterface.get(),
725 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
726 if (res != OK) {
727 ALOGE("%s: Unable to query consumer undequeued"
728 " buffer count for stream %d", __FUNCTION__, mId);
729 return res;
730 }
731 mMaxConsumerBuffers = maxConsumerBuffers;
732
733 ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__,
734 mMaxProducerBuffers, mMaxConsumerBuffers);
735
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700736 mTotalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;
737 mActiveBuffers = 0;
738 mFrameCount = 0;
739 mLastTimestamp = 0;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700740
741 res = native_window_set_buffer_count(mConsumerInterface.get(),
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700742 mTotalBuffers);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700743 if (res != OK) {
744 ALOGE("%s: Unable to set buffer count for stream %d",
745 __FUNCTION__, mId);
746 return res;
747 }
748
749 // Register allocated buffers with HAL device
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700750 buffer_handle_t *buffers = new buffer_handle_t[mTotalBuffers];
751 ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[mTotalBuffers];
752 uint32_t bufferIdx = 0;
753 for (; bufferIdx < mTotalBuffers; bufferIdx++) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700754 res = mConsumerInterface->dequeueBuffer(mConsumerInterface.get(),
755 &anwBuffers[bufferIdx]);
756 if (res != OK) {
757 ALOGE("%s: Unable to dequeue buffer %d for initial registration for"
758 "stream %d", __FUNCTION__, bufferIdx, mId);
759 goto cleanUpBuffers;
760 }
761
762 res = mConsumerInterface->lockBuffer(mConsumerInterface.get(),
763 anwBuffers[bufferIdx]);
764 if (res != OK) {
765 ALOGE("%s: Unable to lock buffer %d for initial registration for"
766 "stream %d", __FUNCTION__, bufferIdx, mId);
767 bufferIdx++;
768 goto cleanUpBuffers;
769 }
770
771 buffers[bufferIdx] = anwBuffers[bufferIdx]->handle;
772 }
773
774 res = mDevice->ops->register_stream_buffers(mDevice,
775 mId,
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700776 mTotalBuffers,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700777 buffers);
778 if (res != OK) {
779 ALOGE("%s: Unable to register buffers with HAL device for stream %d",
780 __FUNCTION__, mId);
781 } else {
782 mState = ACTIVE;
783 }
784
785cleanUpBuffers:
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700786 for (uint32_t i = 0; i < bufferIdx; i++) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700787 res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
788 anwBuffers[i]);
789 if (res != OK) {
790 ALOGE("%s: Unable to cancel buffer %d after registration",
791 __FUNCTION__, i);
792 }
793 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700794 delete[] anwBuffers;
795 delete[] buffers;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700796
797 return res;
798}
799
800status_t Camera2Device::StreamAdapter::disconnect() {
801 status_t res;
802 if (mState >= ALLOCATED) {
803 res = mDevice->ops->release_stream(mDevice, mId);
804 if (res != OK) {
805 ALOGE("%s: Unable to release stream %d",
806 __FUNCTION__, mId);
807 return res;
808 }
809 }
810 if (mState >= CONNECTED) {
811 res = native_window_api_disconnect(mConsumerInterface.get(),
812 NATIVE_WINDOW_API_CAMERA);
813 if (res != OK) {
814 ALOGE("%s: Unable to disconnect stream %d from native window",
815 __FUNCTION__, mId);
816 return res;
817 }
818 }
819 mId = -1;
820 mState = DISCONNECTED;
821 return OK;
822}
823
Eino-Ville Talvalac94cd192012-06-15 12:47:42 -0700824status_t Camera2Device::StreamAdapter::setTransform(int transform) {
825 status_t res;
826 if (mState < CONNECTED) {
827 ALOGE("%s: Cannot set transform on unconnected stream", __FUNCTION__);
828 return INVALID_OPERATION;
829 }
830 res = native_window_set_buffers_transform(mConsumerInterface.get(),
831 transform);
832 if (res != OK) {
833 ALOGE("%s: Unable to configure stream transform to %x: %s (%d)",
834 __FUNCTION__, transform, strerror(-res), res);
835 }
836 return res;
837}
838
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700839status_t Camera2Device::StreamAdapter::dump(int fd,
840 const Vector<String16>& args) {
841 String8 result = String8::format(" Stream %d: %d x %d, format 0x%x\n",
842 mId, mWidth, mHeight, mFormat);
843 result.appendFormat(" size %d, usage 0x%x, requested format 0x%x\n",
844 mSize, mUsage, mFormatRequested);
845 result.appendFormat(" total buffers: %d, dequeued buffers: %d\n",
846 mTotalBuffers, mActiveBuffers);
847 result.appendFormat(" frame count: %d, last timestamp %lld\n",
848 mFrameCount, mLastTimestamp);
849 write(fd, result.string(), result.size());
850 return OK;
851}
852
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700853const camera2_stream_ops *Camera2Device::StreamAdapter::getStreamOps() {
854 return static_cast<camera2_stream_ops *>(this);
855}
856
857ANativeWindow* Camera2Device::StreamAdapter::toANW(
858 const camera2_stream_ops_t *w) {
859 return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get();
860}
861
862int Camera2Device::StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w,
863 buffer_handle_t** buffer) {
864 int res;
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700865 StreamAdapter* stream =
866 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
867 if (stream->mState != ACTIVE) {
868 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700869 return INVALID_OPERATION;
870 }
871
872 ANativeWindow *a = toANW(w);
873 ANativeWindowBuffer* anb;
874 res = a->dequeueBuffer(a, &anb);
875 if (res != OK) return res;
876 res = a->lockBuffer(a, anb);
877 if (res != OK) return res;
878
879 *buffer = &(anb->handle);
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700880 stream->mActiveBuffers++;
881
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700882 ALOGV("%s: Buffer %p", __FUNCTION__, *buffer);
883 return res;
884}
885
886int Camera2Device::StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w,
887 int64_t timestamp,
888 buffer_handle_t* buffer) {
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700889 StreamAdapter *stream =
890 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700891 ALOGV("%s: Stream %d: Buffer %p captured at %lld ns",
892 __FUNCTION__, stream->mId, buffer, timestamp);
893 int state = stream->mState;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700894 if (state != ACTIVE) {
895 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
896 return INVALID_OPERATION;
897 }
898 ANativeWindow *a = toANW(w);
899 status_t err;
900 err = native_window_set_buffers_timestamp(a, timestamp);
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700901 if (err != OK) {
902 ALOGE("%s: Error setting timestamp on native window: %s (%d)",
903 __FUNCTION__, strerror(-err), err);
904 return err;
905 }
906 err = a->queueBuffer(a,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700907 container_of(buffer, ANativeWindowBuffer, handle));
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700908 if (err != OK) {
909 ALOGE("%s: Error queueing buffer to native window: %s (%d)",
910 __FUNCTION__, strerror(-err), err);
911 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700912 stream->mActiveBuffers--;
913 stream->mFrameCount++;
914 stream->mLastTimestamp = timestamp;
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700915 return err;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700916}
917
918int Camera2Device::StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w,
919 buffer_handle_t* buffer) {
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700920 StreamAdapter *stream =
921 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
922 if (stream->mState != ACTIVE) {
923 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700924 return INVALID_OPERATION;
925 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700926 stream->mActiveBuffers--;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700927 ANativeWindow *a = toANW(w);
928 return a->cancelBuffer(a,
929 container_of(buffer, ANativeWindowBuffer, handle));
930}
931
932int Camera2Device::StreamAdapter::set_crop(const camera2_stream_ops_t* w,
933 int left, int top, int right, int bottom) {
934 int state = static_cast<const StreamAdapter*>(w)->mState;
935 if (state != ACTIVE) {
936 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
937 return INVALID_OPERATION;
938 }
939 ANativeWindow *a = toANW(w);
940 android_native_rect_t crop = { left, top, right, bottom };
941 return native_window_set_crop(a, &crop);
942}
943
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700944
945}; // namespace android