blob: 7db04ff08b7e9df21569edf3ffad9c9d202f0013 [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 Talvala6db981c2012-05-21 18:54:30 -0700108camera_metadata_t *Camera2Device::info() {
109 ALOGV("%s: E", __FUNCTION__);
110
111 return mDeviceInfo;
112}
113
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700114status_t Camera2Device::capture(camera_metadata_t* request) {
115 ALOGV("%s: E", __FUNCTION__);
116
117 mRequestQueue.enqueue(request);
118 return OK;
119}
120
121
122status_t Camera2Device::setStreamingRequest(camera_metadata_t* request) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700123 ALOGV("%s: E", __FUNCTION__);
124
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700125 mRequestQueue.setStreamSlot(request);
126 return OK;
127}
128
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700129status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700130 uint32_t width, uint32_t height, int format, size_t size, int *id) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700131 status_t res;
132 ALOGV("%s: E", __FUNCTION__);
133
134 sp<StreamAdapter> stream = new StreamAdapter(mDevice);
135
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700136 res = stream->connectToDevice(consumer, width, height, format, size);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700137 if (res != OK) {
138 ALOGE("%s: Camera %d: Unable to create stream (%d x %d, format %x):"
139 "%s (%d)",
140 __FUNCTION__, mId, width, height, format, strerror(-res), res);
141 return res;
142 }
143
144 *id = stream->getId();
145
146 mStreams.push_back(stream);
147 return OK;
148}
149
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700150status_t Camera2Device::getStreamInfo(int id,
151 uint32_t *width, uint32_t *height, uint32_t *format) {
152 ALOGV("%s: E", __FUNCTION__);
153 bool found = false;
154 StreamList::iterator streamI;
155 for (streamI = mStreams.begin();
156 streamI != mStreams.end(); streamI++) {
157 if ((*streamI)->getId() == id) {
158 found = true;
159 break;
160 }
161 }
162 if (!found) {
163 ALOGE("%s: Camera %d: Stream %d does not exist",
164 __FUNCTION__, mId, id);
165 return BAD_VALUE;
166 }
167
168 if (width) *width = (*streamI)->getWidth();
169 if (height) *height = (*streamI)->getHeight();
170 if (format) *format = (*streamI)->getFormat();
171
172 return OK;
173}
174
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700175status_t Camera2Device::deleteStream(int id) {
176 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700177 bool found = false;
178 for (StreamList::iterator streamI = mStreams.begin();
179 streamI != mStreams.end(); streamI++) {
180 if ((*streamI)->getId() == id) {
Eino-Ville Talvala4ecfec32012-06-12 17:13:48 -0700181 status_t res = (*streamI)->disconnect();
182 if (res != OK) {
183 ALOGE("%s: Unable to disconnect stream %d from HAL device: "
184 "%s (%d)", __FUNCTION__, id, strerror(-res), res);
185 return res;
186 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700187 mStreams.erase(streamI);
188 found = true;
189 break;
190 }
191 }
192 if (!found) {
193 ALOGE("%s: Camera %d: Unable to find stream %d to delete",
194 __FUNCTION__, mId, id);
195 return BAD_VALUE;
196 }
197 return OK;
198}
199
200status_t Camera2Device::createDefaultRequest(int templateId,
201 camera_metadata_t **request) {
202 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700203 return mDevice->ops->construct_default_request(
204 mDevice, templateId, request);
205}
206
207status_t Camera2Device::waitUntilDrained() {
208 static const uint32_t kSleepTime = 50000; // 50 ms
209 static const uint32_t kMaxSleepTime = 10000000; // 10 s
210
211 if (mRequestQueue.getBufferCount() ==
212 CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS) return INVALID_OPERATION;
213
214 // TODO: Set up notifications from HAL, instead of sleeping here
215 uint32_t totalTime = 0;
216 while (mDevice->ops->get_in_progress_count(mDevice) > 0) {
217 usleep(kSleepTime);
218 totalTime += kSleepTime;
219 if (totalTime > kMaxSleepTime) {
220 ALOGE("%s: Waited %d us, requests still in flight", __FUNCTION__,
221 totalTime);
222 return TIMED_OUT;
223 }
224 }
225 return OK;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700226}
227
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700228/**
229 * Camera2Device::MetadataQueue
230 */
231
232Camera2Device::MetadataQueue::MetadataQueue():
233 mDevice(NULL),
234 mFrameCount(0),
235 mCount(0),
236 mStreamSlotCount(0),
237 mSignalConsumer(true)
238{
239 camera2_request_queue_src_ops::dequeue_request = consumer_dequeue;
240 camera2_request_queue_src_ops::request_count = consumer_buffer_count;
241 camera2_request_queue_src_ops::free_request = consumer_free;
242
243 camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue;
244 camera2_frame_queue_dst_ops::cancel_frame = producer_cancel;
245 camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue;
246}
247
248Camera2Device::MetadataQueue::~MetadataQueue() {
249 Mutex::Autolock l(mMutex);
250 freeBuffers(mEntries.begin(), mEntries.end());
251 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
252}
253
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700254// Connect to camera2 HAL as consumer (input requests/reprocessing)
255status_t Camera2Device::MetadataQueue::setConsumerDevice(camera2_device_t *d) {
256 status_t res;
257 res = d->ops->set_request_queue_src_ops(d,
258 this);
259 if (res != OK) return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700260 mDevice = d;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700261 return OK;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700262}
263
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700264status_t Camera2Device::MetadataQueue::setProducerDevice(camera2_device_t *d) {
265 status_t res;
266 res = d->ops->set_frame_queue_dst_ops(d,
267 this);
268 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700269}
270
271// Real interfaces
272status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700273 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700274 Mutex::Autolock l(mMutex);
275
276 mCount++;
277 mEntries.push_back(buf);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700278
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700279 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700280}
281
282int Camera2Device::MetadataQueue::getBufferCount() {
283 Mutex::Autolock l(mMutex);
284 if (mStreamSlotCount > 0) {
285 return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS;
286 }
287 return mCount;
288}
289
290status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
291 bool incrementCount)
292{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700293 ALOGV("%s: E", __FUNCTION__);
294 status_t res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700295 Mutex::Autolock l(mMutex);
296
297 if (mCount == 0) {
298 if (mStreamSlotCount == 0) {
299 ALOGV("%s: Empty", __FUNCTION__);
300 *buf = NULL;
301 mSignalConsumer = true;
302 return OK;
303 }
304 ALOGV("%s: Streaming %d frames to queue", __FUNCTION__,
305 mStreamSlotCount);
306
307 for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin();
308 slotEntry != mStreamSlot.end();
309 slotEntry++ ) {
310 size_t entries = get_camera_metadata_entry_count(*slotEntry);
311 size_t dataBytes = get_camera_metadata_data_count(*slotEntry);
312
313 camera_metadata_t *copy =
314 allocate_camera_metadata(entries, dataBytes);
315 append_camera_metadata(copy, *slotEntry);
316 mEntries.push_back(copy);
317 }
318 mCount = mStreamSlotCount;
319 }
320 ALOGV("MetadataQueue: deque (%d buffers)", mCount);
321 camera_metadata_t *b = *(mEntries.begin());
322 mEntries.erase(mEntries.begin());
323
324 if (incrementCount) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700325 camera_metadata_entry_t frameCount;
326 res = find_camera_metadata_entry(b,
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700327 ANDROID_REQUEST_FRAME_COUNT,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700328 &frameCount);
329 if (res != OK) {
330 ALOGE("%s: Unable to add frame count: %s (%d)",
331 __FUNCTION__, strerror(-res), res);
332 } else {
333 *frameCount.data.i32 = mFrameCount;
334 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700335 mFrameCount++;
336 }
337
338 *buf = b;
339 mCount--;
340
341 return OK;
342}
343
344status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)
345{
346 Mutex::Autolock l(mMutex);
347 status_t res;
348 while (mCount == 0) {
349 res = notEmpty.waitRelative(mMutex,timeout);
350 if (res != OK) return res;
351 }
352 return OK;
353}
354
355status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
356{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700357 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700358 Mutex::Autolock l(mMutex);
359 if (buf == NULL) {
360 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
361 mStreamSlotCount = 0;
362 return OK;
363 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700364 camera_metadata_t *buf2 = clone_camera_metadata(buf);
365 if (!buf2) {
366 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
367 return NO_MEMORY;
368 }
369
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700370 if (mStreamSlotCount > 1) {
371 List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
372 freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
373 mStreamSlotCount = 1;
374 }
375 if (mStreamSlotCount == 1) {
376 free_camera_metadata( *(mStreamSlot.begin()) );
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700377 *(mStreamSlot.begin()) = buf2;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700378 } else {
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700379 mStreamSlot.push_front(buf2);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700380 mStreamSlotCount = 1;
381 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700382 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700383}
384
385status_t Camera2Device::MetadataQueue::setStreamSlot(
386 const List<camera_metadata_t*> &bufs)
387{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700388 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700389 Mutex::Autolock l(mMutex);
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700390 status_t res;
391
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700392 if (mStreamSlotCount > 0) {
393 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
394 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700395 mStreamSlotCount = 0;
396 for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
397 r != bufs.end(); r++) {
398 camera_metadata_t *r2 = clone_camera_metadata(*r);
399 if (!r2) {
400 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
401 return NO_MEMORY;
402 }
403 mStreamSlot.push_back(r2);
404 mStreamSlotCount++;
405 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700406 return signalConsumerLocked();
407}
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700408
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700409status_t Camera2Device::MetadataQueue::signalConsumerLocked() {
410 status_t res = OK;
411 notEmpty.signal();
412 if (mSignalConsumer && mDevice != NULL) {
413 mSignalConsumer = false;
414
415 mMutex.unlock();
416 ALOGV("%s: Signaling consumer", __FUNCTION__);
417 res = mDevice->ops->notify_request_queue_not_empty(mDevice);
418 mMutex.lock();
419 }
420 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700421}
422
423status_t Camera2Device::MetadataQueue::freeBuffers(
424 List<camera_metadata_t*>::iterator start,
425 List<camera_metadata_t*>::iterator end)
426{
427 while (start != end) {
428 free_camera_metadata(*start);
429 start = mStreamSlot.erase(start);
430 }
431 return OK;
432}
433
434Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
435 const camera2_request_queue_src_ops_t *q)
436{
437 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
438 return const_cast<MetadataQueue*>(cmq);
439}
440
441Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
442 const camera2_frame_queue_dst_ops_t *q)
443{
444 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
445 return const_cast<MetadataQueue*>(cmq);
446}
447
448int Camera2Device::MetadataQueue::consumer_buffer_count(
449 const camera2_request_queue_src_ops_t *q)
450{
451 MetadataQueue *queue = getInstance(q);
452 return queue->getBufferCount();
453}
454
455int Camera2Device::MetadataQueue::consumer_dequeue(
456 const camera2_request_queue_src_ops_t *q,
457 camera_metadata_t **buffer)
458{
459 MetadataQueue *queue = getInstance(q);
460 return queue->dequeue(buffer, true);
461}
462
463int Camera2Device::MetadataQueue::consumer_free(
464 const camera2_request_queue_src_ops_t *q,
465 camera_metadata_t *old_buffer)
466{
467 MetadataQueue *queue = getInstance(q);
468 free_camera_metadata(old_buffer);
469 return OK;
470}
471
472int Camera2Device::MetadataQueue::producer_dequeue(
473 const camera2_frame_queue_dst_ops_t *q,
474 size_t entries, size_t bytes,
475 camera_metadata_t **buffer)
476{
477 camera_metadata_t *new_buffer =
478 allocate_camera_metadata(entries, bytes);
479 if (new_buffer == NULL) return NO_MEMORY;
480 *buffer = new_buffer;
481 return OK;
482}
483
484int Camera2Device::MetadataQueue::producer_cancel(
485 const camera2_frame_queue_dst_ops_t *q,
486 camera_metadata_t *old_buffer)
487{
488 free_camera_metadata(old_buffer);
489 return OK;
490}
491
492int Camera2Device::MetadataQueue::producer_enqueue(
493 const camera2_frame_queue_dst_ops_t *q,
494 camera_metadata_t *filled_buffer)
495{
496 MetadataQueue *queue = getInstance(q);
497 return queue->enqueue(filled_buffer);
498}
499
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700500/**
501 * Camera2Device::StreamAdapter
502 */
503
504#ifndef container_of
505#define container_of(ptr, type, member) \
506 (type *)((char*)(ptr) - offsetof(type, member))
507#endif
508
509Camera2Device::StreamAdapter::StreamAdapter(camera2_device_t *d):
510 mState(DISCONNECTED),
511 mDevice(d),
512 mId(-1),
513 mWidth(0), mHeight(0), mFormatRequested(0)
514{
515 camera2_stream_ops::dequeue_buffer = dequeue_buffer;
516 camera2_stream_ops::enqueue_buffer = enqueue_buffer;
517 camera2_stream_ops::cancel_buffer = cancel_buffer;
518 camera2_stream_ops::set_crop = set_crop;
519}
520
521Camera2Device::StreamAdapter::~StreamAdapter() {
522 disconnect();
523}
524
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700525status_t Camera2Device::StreamAdapter::connectToDevice(
526 sp<ANativeWindow> consumer,
527 uint32_t width, uint32_t height, int format, size_t size) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700528 status_t res;
529
530 if (mState != DISCONNECTED) return INVALID_OPERATION;
531 if (consumer == NULL) {
532 ALOGE("%s: Null consumer passed to stream adapter", __FUNCTION__);
533 return BAD_VALUE;
534 }
535
536 mConsumerInterface = consumer;
537 mWidth = width;
538 mHeight = height;
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700539 mSize = (format == HAL_PIXEL_FORMAT_BLOB) ? size : 0;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700540 mFormatRequested = format;
541
542 // Allocate device-side stream interface
543
544 uint32_t id;
545 uint32_t formatActual;
546 uint32_t usage;
547 uint32_t maxBuffers = 2;
548 res = mDevice->ops->allocate_stream(mDevice,
549 mWidth, mHeight, mFormatRequested, getStreamOps(),
550 &id, &formatActual, &usage, &maxBuffers);
551 if (res != OK) {
552 ALOGE("%s: Device stream allocation failed: %s (%d)",
553 __FUNCTION__, strerror(-res), res);
554 return res;
555 }
556
557 mId = id;
558 mFormat = formatActual;
559 mUsage = usage;
560 mMaxProducerBuffers = maxBuffers;
561
562 mState = ALLOCATED;
563
564 // Configure consumer-side ANativeWindow interface
565 res = native_window_api_connect(mConsumerInterface.get(),
566 NATIVE_WINDOW_API_CAMERA);
567 if (res != OK) {
568 ALOGE("%s: Unable to connect to native window for stream %d",
569 __FUNCTION__, mId);
570
571 return res;
572 }
573
574 mState = CONNECTED;
575
576 res = native_window_set_usage(mConsumerInterface.get(), mUsage);
577 if (res != OK) {
578 ALOGE("%s: Unable to configure usage %08x for stream %d",
579 __FUNCTION__, mUsage, mId);
580 return res;
581 }
582
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700583 res = native_window_set_scaling_mode(mConsumerInterface.get(),
584 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
585 if (res != OK) {
586 ALOGE("%s: Unable to configure stream scaling: %s (%d)",
587 __FUNCTION__, strerror(-res), res);
588 return res;
589 }
590
591 res = native_window_set_buffers_transform(mConsumerInterface.get(), 0);
592 if (res != OK) {
593 ALOGE("%s: Unable to configure stream transform: %s (%d)",
594 __FUNCTION__, strerror(-res), res);
595 return res;
596 }
597
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700598 if (mFormat == HAL_PIXEL_FORMAT_BLOB) {
599 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
600 mSize, 1, mFormat);
601 if (res != OK) {
602 ALOGE("%s: Unable to configure compressed stream buffer geometry"
603 " %d x %d, size %d for stream %d",
604 __FUNCTION__, mWidth, mHeight, mSize, mId);
605 return res;
606 }
607 } else {
608 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
609 mWidth, mHeight, mFormat);
610 if (res != OK) {
611 ALOGE("%s: Unable to configure stream buffer geometry"
612 " %d x %d, format 0x%x for stream %d",
613 __FUNCTION__, mWidth, mHeight, mFormat, mId);
614 return res;
615 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700616 }
617
618 int maxConsumerBuffers;
619 res = mConsumerInterface->query(mConsumerInterface.get(),
620 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
621 if (res != OK) {
622 ALOGE("%s: Unable to query consumer undequeued"
623 " buffer count for stream %d", __FUNCTION__, mId);
624 return res;
625 }
626 mMaxConsumerBuffers = maxConsumerBuffers;
627
628 ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__,
629 mMaxProducerBuffers, mMaxConsumerBuffers);
630
631 int totalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;
632
633 res = native_window_set_buffer_count(mConsumerInterface.get(),
634 totalBuffers);
635 if (res != OK) {
636 ALOGE("%s: Unable to set buffer count for stream %d",
637 __FUNCTION__, mId);
638 return res;
639 }
640
641 // Register allocated buffers with HAL device
642 buffer_handle_t *buffers = new buffer_handle_t[totalBuffers];
643 ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[totalBuffers];
644 int bufferIdx = 0;
645 for (; bufferIdx < totalBuffers; bufferIdx++) {
646 res = mConsumerInterface->dequeueBuffer(mConsumerInterface.get(),
647 &anwBuffers[bufferIdx]);
648 if (res != OK) {
649 ALOGE("%s: Unable to dequeue buffer %d for initial registration for"
650 "stream %d", __FUNCTION__, bufferIdx, mId);
651 goto cleanUpBuffers;
652 }
653
654 res = mConsumerInterface->lockBuffer(mConsumerInterface.get(),
655 anwBuffers[bufferIdx]);
656 if (res != OK) {
657 ALOGE("%s: Unable to lock buffer %d for initial registration for"
658 "stream %d", __FUNCTION__, bufferIdx, mId);
659 bufferIdx++;
660 goto cleanUpBuffers;
661 }
662
663 buffers[bufferIdx] = anwBuffers[bufferIdx]->handle;
664 }
665
666 res = mDevice->ops->register_stream_buffers(mDevice,
667 mId,
668 totalBuffers,
669 buffers);
670 if (res != OK) {
671 ALOGE("%s: Unable to register buffers with HAL device for stream %d",
672 __FUNCTION__, mId);
673 } else {
674 mState = ACTIVE;
675 }
676
677cleanUpBuffers:
678 for (int i = 0; i < bufferIdx; i++) {
679 res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
680 anwBuffers[i]);
681 if (res != OK) {
682 ALOGE("%s: Unable to cancel buffer %d after registration",
683 __FUNCTION__, i);
684 }
685 }
686 delete anwBuffers;
687 delete buffers;
688
689 return res;
690}
691
692status_t Camera2Device::StreamAdapter::disconnect() {
693 status_t res;
694 if (mState >= ALLOCATED) {
695 res = mDevice->ops->release_stream(mDevice, mId);
696 if (res != OK) {
697 ALOGE("%s: Unable to release stream %d",
698 __FUNCTION__, mId);
699 return res;
700 }
701 }
702 if (mState >= CONNECTED) {
703 res = native_window_api_disconnect(mConsumerInterface.get(),
704 NATIVE_WINDOW_API_CAMERA);
705 if (res != OK) {
706 ALOGE("%s: Unable to disconnect stream %d from native window",
707 __FUNCTION__, mId);
708 return res;
709 }
710 }
711 mId = -1;
712 mState = DISCONNECTED;
713 return OK;
714}
715
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700716const camera2_stream_ops *Camera2Device::StreamAdapter::getStreamOps() {
717 return static_cast<camera2_stream_ops *>(this);
718}
719
720ANativeWindow* Camera2Device::StreamAdapter::toANW(
721 const camera2_stream_ops_t *w) {
722 return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get();
723}
724
725int Camera2Device::StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w,
726 buffer_handle_t** buffer) {
727 int res;
728 int state = static_cast<const StreamAdapter*>(w)->mState;
729 if (state != ACTIVE) {
730 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
731 return INVALID_OPERATION;
732 }
733
734 ANativeWindow *a = toANW(w);
735 ANativeWindowBuffer* anb;
736 res = a->dequeueBuffer(a, &anb);
737 if (res != OK) return res;
738 res = a->lockBuffer(a, anb);
739 if (res != OK) return res;
740
741 *buffer = &(anb->handle);
742 ALOGV("%s: Buffer %p", __FUNCTION__, *buffer);
743 return res;
744}
745
746int Camera2Device::StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w,
747 int64_t timestamp,
748 buffer_handle_t* buffer) {
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700749 const StreamAdapter *stream = static_cast<const StreamAdapter*>(w);
750 ALOGV("%s: Stream %d: Buffer %p captured at %lld ns",
751 __FUNCTION__, stream->mId, buffer, timestamp);
752 int state = stream->mState;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700753 if (state != ACTIVE) {
754 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
755 return INVALID_OPERATION;
756 }
757 ANativeWindow *a = toANW(w);
758 status_t err;
759 err = native_window_set_buffers_timestamp(a, timestamp);
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700760 if (err != OK) {
761 ALOGE("%s: Error setting timestamp on native window: %s (%d)",
762 __FUNCTION__, strerror(-err), err);
763 return err;
764 }
765 err = a->queueBuffer(a,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700766 container_of(buffer, ANativeWindowBuffer, handle));
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700767 if (err != OK) {
768 ALOGE("%s: Error queueing buffer to native window: %s (%d)",
769 __FUNCTION__, strerror(-err), err);
770 }
771 return err;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700772}
773
774int Camera2Device::StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w,
775 buffer_handle_t* buffer) {
776 int state = static_cast<const StreamAdapter*>(w)->mState;
777 if (state != ACTIVE) {
778 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
779 return INVALID_OPERATION;
780 }
781 ANativeWindow *a = toANW(w);
782 return a->cancelBuffer(a,
783 container_of(buffer, ANativeWindowBuffer, handle));
784}
785
786int Camera2Device::StreamAdapter::set_crop(const camera2_stream_ops_t* w,
787 int left, int top, int right, int bottom) {
788 int state = static_cast<const StreamAdapter*>(w)->mState;
789 if (state != ACTIVE) {
790 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
791 return INVALID_OPERATION;
792 }
793 ANativeWindow *a = toANW(w);
794 android_native_rect_t crop = { left, top, right, bottom };
795 return native_window_set_crop(a, &crop);
796}
797
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700798
799}; // namespace android