blob: 8cb872ae0df6879147915a9ca8d77b7d65be8670 [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__);
177
178 bool found = false;
179 for (StreamList::iterator streamI = mStreams.begin();
180 streamI != mStreams.end(); streamI++) {
181 if ((*streamI)->getId() == id) {
182 mStreams.erase(streamI);
183 found = true;
184 break;
185 }
186 }
187 if (!found) {
188 ALOGE("%s: Camera %d: Unable to find stream %d to delete",
189 __FUNCTION__, mId, id);
190 return BAD_VALUE;
191 }
192 return OK;
193}
194
195status_t Camera2Device::createDefaultRequest(int templateId,
196 camera_metadata_t **request) {
197 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700198 return mDevice->ops->construct_default_request(
199 mDevice, templateId, request);
200}
201
202status_t Camera2Device::waitUntilDrained() {
203 static const uint32_t kSleepTime = 50000; // 50 ms
204 static const uint32_t kMaxSleepTime = 10000000; // 10 s
205
206 if (mRequestQueue.getBufferCount() ==
207 CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS) return INVALID_OPERATION;
208
209 // TODO: Set up notifications from HAL, instead of sleeping here
210 uint32_t totalTime = 0;
211 while (mDevice->ops->get_in_progress_count(mDevice) > 0) {
212 usleep(kSleepTime);
213 totalTime += kSleepTime;
214 if (totalTime > kMaxSleepTime) {
215 ALOGE("%s: Waited %d us, requests still in flight", __FUNCTION__,
216 totalTime);
217 return TIMED_OUT;
218 }
219 }
220 return OK;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700221}
222
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700223/**
224 * Camera2Device::MetadataQueue
225 */
226
227Camera2Device::MetadataQueue::MetadataQueue():
228 mDevice(NULL),
229 mFrameCount(0),
230 mCount(0),
231 mStreamSlotCount(0),
232 mSignalConsumer(true)
233{
234 camera2_request_queue_src_ops::dequeue_request = consumer_dequeue;
235 camera2_request_queue_src_ops::request_count = consumer_buffer_count;
236 camera2_request_queue_src_ops::free_request = consumer_free;
237
238 camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue;
239 camera2_frame_queue_dst_ops::cancel_frame = producer_cancel;
240 camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue;
241}
242
243Camera2Device::MetadataQueue::~MetadataQueue() {
244 Mutex::Autolock l(mMutex);
245 freeBuffers(mEntries.begin(), mEntries.end());
246 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
247}
248
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700249// Connect to camera2 HAL as consumer (input requests/reprocessing)
250status_t Camera2Device::MetadataQueue::setConsumerDevice(camera2_device_t *d) {
251 status_t res;
252 res = d->ops->set_request_queue_src_ops(d,
253 this);
254 if (res != OK) return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700255 mDevice = d;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700256 return OK;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700257}
258
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700259status_t Camera2Device::MetadataQueue::setProducerDevice(camera2_device_t *d) {
260 status_t res;
261 res = d->ops->set_frame_queue_dst_ops(d,
262 this);
263 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700264}
265
266// Real interfaces
267status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700268 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700269 Mutex::Autolock l(mMutex);
270
271 mCount++;
272 mEntries.push_back(buf);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700273
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700274 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700275}
276
277int Camera2Device::MetadataQueue::getBufferCount() {
278 Mutex::Autolock l(mMutex);
279 if (mStreamSlotCount > 0) {
280 return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS;
281 }
282 return mCount;
283}
284
285status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
286 bool incrementCount)
287{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700288 ALOGV("%s: E", __FUNCTION__);
289 status_t res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700290 Mutex::Autolock l(mMutex);
291
292 if (mCount == 0) {
293 if (mStreamSlotCount == 0) {
294 ALOGV("%s: Empty", __FUNCTION__);
295 *buf = NULL;
296 mSignalConsumer = true;
297 return OK;
298 }
299 ALOGV("%s: Streaming %d frames to queue", __FUNCTION__,
300 mStreamSlotCount);
301
302 for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin();
303 slotEntry != mStreamSlot.end();
304 slotEntry++ ) {
305 size_t entries = get_camera_metadata_entry_count(*slotEntry);
306 size_t dataBytes = get_camera_metadata_data_count(*slotEntry);
307
308 camera_metadata_t *copy =
309 allocate_camera_metadata(entries, dataBytes);
310 append_camera_metadata(copy, *slotEntry);
311 mEntries.push_back(copy);
312 }
313 mCount = mStreamSlotCount;
314 }
315 ALOGV("MetadataQueue: deque (%d buffers)", mCount);
316 camera_metadata_t *b = *(mEntries.begin());
317 mEntries.erase(mEntries.begin());
318
319 if (incrementCount) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700320 camera_metadata_entry_t frameCount;
321 res = find_camera_metadata_entry(b,
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700322 ANDROID_REQUEST_FRAME_COUNT,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700323 &frameCount);
324 if (res != OK) {
325 ALOGE("%s: Unable to add frame count: %s (%d)",
326 __FUNCTION__, strerror(-res), res);
327 } else {
328 *frameCount.data.i32 = mFrameCount;
329 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700330 mFrameCount++;
331 }
332
333 *buf = b;
334 mCount--;
335
336 return OK;
337}
338
339status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)
340{
341 Mutex::Autolock l(mMutex);
342 status_t res;
343 while (mCount == 0) {
344 res = notEmpty.waitRelative(mMutex,timeout);
345 if (res != OK) return res;
346 }
347 return OK;
348}
349
350status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
351{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700352 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700353 Mutex::Autolock l(mMutex);
354 if (buf == NULL) {
355 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
356 mStreamSlotCount = 0;
357 return OK;
358 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700359 camera_metadata_t *buf2 = clone_camera_metadata(buf);
360 if (!buf2) {
361 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
362 return NO_MEMORY;
363 }
364
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700365 if (mStreamSlotCount > 1) {
366 List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
367 freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
368 mStreamSlotCount = 1;
369 }
370 if (mStreamSlotCount == 1) {
371 free_camera_metadata( *(mStreamSlot.begin()) );
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700372 *(mStreamSlot.begin()) = buf2;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700373 } else {
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700374 mStreamSlot.push_front(buf2);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700375 mStreamSlotCount = 1;
376 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700377 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700378}
379
380status_t Camera2Device::MetadataQueue::setStreamSlot(
381 const List<camera_metadata_t*> &bufs)
382{
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700383 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700384 Mutex::Autolock l(mMutex);
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700385 status_t res;
386
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700387 if (mStreamSlotCount > 0) {
388 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
389 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700390 mStreamSlotCount = 0;
391 for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
392 r != bufs.end(); r++) {
393 camera_metadata_t *r2 = clone_camera_metadata(*r);
394 if (!r2) {
395 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
396 return NO_MEMORY;
397 }
398 mStreamSlot.push_back(r2);
399 mStreamSlotCount++;
400 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700401 return signalConsumerLocked();
402}
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700403
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700404status_t Camera2Device::MetadataQueue::signalConsumerLocked() {
405 status_t res = OK;
406 notEmpty.signal();
407 if (mSignalConsumer && mDevice != NULL) {
408 mSignalConsumer = false;
409
410 mMutex.unlock();
411 ALOGV("%s: Signaling consumer", __FUNCTION__);
412 res = mDevice->ops->notify_request_queue_not_empty(mDevice);
413 mMutex.lock();
414 }
415 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700416}
417
418status_t Camera2Device::MetadataQueue::freeBuffers(
419 List<camera_metadata_t*>::iterator start,
420 List<camera_metadata_t*>::iterator end)
421{
422 while (start != end) {
423 free_camera_metadata(*start);
424 start = mStreamSlot.erase(start);
425 }
426 return OK;
427}
428
429Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
430 const camera2_request_queue_src_ops_t *q)
431{
432 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
433 return const_cast<MetadataQueue*>(cmq);
434}
435
436Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
437 const camera2_frame_queue_dst_ops_t *q)
438{
439 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
440 return const_cast<MetadataQueue*>(cmq);
441}
442
443int Camera2Device::MetadataQueue::consumer_buffer_count(
444 const camera2_request_queue_src_ops_t *q)
445{
446 MetadataQueue *queue = getInstance(q);
447 return queue->getBufferCount();
448}
449
450int Camera2Device::MetadataQueue::consumer_dequeue(
451 const camera2_request_queue_src_ops_t *q,
452 camera_metadata_t **buffer)
453{
454 MetadataQueue *queue = getInstance(q);
455 return queue->dequeue(buffer, true);
456}
457
458int Camera2Device::MetadataQueue::consumer_free(
459 const camera2_request_queue_src_ops_t *q,
460 camera_metadata_t *old_buffer)
461{
462 MetadataQueue *queue = getInstance(q);
463 free_camera_metadata(old_buffer);
464 return OK;
465}
466
467int Camera2Device::MetadataQueue::producer_dequeue(
468 const camera2_frame_queue_dst_ops_t *q,
469 size_t entries, size_t bytes,
470 camera_metadata_t **buffer)
471{
472 camera_metadata_t *new_buffer =
473 allocate_camera_metadata(entries, bytes);
474 if (new_buffer == NULL) return NO_MEMORY;
475 *buffer = new_buffer;
476 return OK;
477}
478
479int Camera2Device::MetadataQueue::producer_cancel(
480 const camera2_frame_queue_dst_ops_t *q,
481 camera_metadata_t *old_buffer)
482{
483 free_camera_metadata(old_buffer);
484 return OK;
485}
486
487int Camera2Device::MetadataQueue::producer_enqueue(
488 const camera2_frame_queue_dst_ops_t *q,
489 camera_metadata_t *filled_buffer)
490{
491 MetadataQueue *queue = getInstance(q);
492 return queue->enqueue(filled_buffer);
493}
494
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700495/**
496 * Camera2Device::StreamAdapter
497 */
498
499#ifndef container_of
500#define container_of(ptr, type, member) \
501 (type *)((char*)(ptr) - offsetof(type, member))
502#endif
503
504Camera2Device::StreamAdapter::StreamAdapter(camera2_device_t *d):
505 mState(DISCONNECTED),
506 mDevice(d),
507 mId(-1),
508 mWidth(0), mHeight(0), mFormatRequested(0)
509{
510 camera2_stream_ops::dequeue_buffer = dequeue_buffer;
511 camera2_stream_ops::enqueue_buffer = enqueue_buffer;
512 camera2_stream_ops::cancel_buffer = cancel_buffer;
513 camera2_stream_ops::set_crop = set_crop;
514}
515
516Camera2Device::StreamAdapter::~StreamAdapter() {
517 disconnect();
518}
519
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700520status_t Camera2Device::StreamAdapter::connectToDevice(
521 sp<ANativeWindow> consumer,
522 uint32_t width, uint32_t height, int format, size_t size) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700523 status_t res;
524
525 if (mState != DISCONNECTED) return INVALID_OPERATION;
526 if (consumer == NULL) {
527 ALOGE("%s: Null consumer passed to stream adapter", __FUNCTION__);
528 return BAD_VALUE;
529 }
530
531 mConsumerInterface = consumer;
532 mWidth = width;
533 mHeight = height;
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700534 mSize = (format == HAL_PIXEL_FORMAT_BLOB) ? size : 0;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700535 mFormatRequested = format;
536
537 // Allocate device-side stream interface
538
539 uint32_t id;
540 uint32_t formatActual;
541 uint32_t usage;
542 uint32_t maxBuffers = 2;
543 res = mDevice->ops->allocate_stream(mDevice,
544 mWidth, mHeight, mFormatRequested, getStreamOps(),
545 &id, &formatActual, &usage, &maxBuffers);
546 if (res != OK) {
547 ALOGE("%s: Device stream allocation failed: %s (%d)",
548 __FUNCTION__, strerror(-res), res);
549 return res;
550 }
551
552 mId = id;
553 mFormat = formatActual;
554 mUsage = usage;
555 mMaxProducerBuffers = maxBuffers;
556
557 mState = ALLOCATED;
558
559 // Configure consumer-side ANativeWindow interface
560 res = native_window_api_connect(mConsumerInterface.get(),
561 NATIVE_WINDOW_API_CAMERA);
562 if (res != OK) {
563 ALOGE("%s: Unable to connect to native window for stream %d",
564 __FUNCTION__, mId);
565
566 return res;
567 }
568
569 mState = CONNECTED;
570
571 res = native_window_set_usage(mConsumerInterface.get(), mUsage);
572 if (res != OK) {
573 ALOGE("%s: Unable to configure usage %08x for stream %d",
574 __FUNCTION__, mUsage, mId);
575 return res;
576 }
577
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700578 res = native_window_set_scaling_mode(mConsumerInterface.get(),
579 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
580 if (res != OK) {
581 ALOGE("%s: Unable to configure stream scaling: %s (%d)",
582 __FUNCTION__, strerror(-res), res);
583 return res;
584 }
585
586 res = native_window_set_buffers_transform(mConsumerInterface.get(), 0);
587 if (res != OK) {
588 ALOGE("%s: Unable to configure stream transform: %s (%d)",
589 __FUNCTION__, strerror(-res), res);
590 return res;
591 }
592
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700593 if (mFormat == HAL_PIXEL_FORMAT_BLOB) {
594 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
595 mSize, 1, mFormat);
596 if (res != OK) {
597 ALOGE("%s: Unable to configure compressed stream buffer geometry"
598 " %d x %d, size %d for stream %d",
599 __FUNCTION__, mWidth, mHeight, mSize, mId);
600 return res;
601 }
602 } else {
603 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
604 mWidth, mHeight, mFormat);
605 if (res != OK) {
606 ALOGE("%s: Unable to configure stream buffer geometry"
607 " %d x %d, format 0x%x for stream %d",
608 __FUNCTION__, mWidth, mHeight, mFormat, mId);
609 return res;
610 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700611 }
612
613 int maxConsumerBuffers;
614 res = mConsumerInterface->query(mConsumerInterface.get(),
615 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
616 if (res != OK) {
617 ALOGE("%s: Unable to query consumer undequeued"
618 " buffer count for stream %d", __FUNCTION__, mId);
619 return res;
620 }
621 mMaxConsumerBuffers = maxConsumerBuffers;
622
623 ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__,
624 mMaxProducerBuffers, mMaxConsumerBuffers);
625
626 int totalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;
627
628 res = native_window_set_buffer_count(mConsumerInterface.get(),
629 totalBuffers);
630 if (res != OK) {
631 ALOGE("%s: Unable to set buffer count for stream %d",
632 __FUNCTION__, mId);
633 return res;
634 }
635
636 // Register allocated buffers with HAL device
637 buffer_handle_t *buffers = new buffer_handle_t[totalBuffers];
638 ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[totalBuffers];
639 int bufferIdx = 0;
640 for (; bufferIdx < totalBuffers; bufferIdx++) {
641 res = mConsumerInterface->dequeueBuffer(mConsumerInterface.get(),
642 &anwBuffers[bufferIdx]);
643 if (res != OK) {
644 ALOGE("%s: Unable to dequeue buffer %d for initial registration for"
645 "stream %d", __FUNCTION__, bufferIdx, mId);
646 goto cleanUpBuffers;
647 }
648
649 res = mConsumerInterface->lockBuffer(mConsumerInterface.get(),
650 anwBuffers[bufferIdx]);
651 if (res != OK) {
652 ALOGE("%s: Unable to lock buffer %d for initial registration for"
653 "stream %d", __FUNCTION__, bufferIdx, mId);
654 bufferIdx++;
655 goto cleanUpBuffers;
656 }
657
658 buffers[bufferIdx] = anwBuffers[bufferIdx]->handle;
659 }
660
661 res = mDevice->ops->register_stream_buffers(mDevice,
662 mId,
663 totalBuffers,
664 buffers);
665 if (res != OK) {
666 ALOGE("%s: Unable to register buffers with HAL device for stream %d",
667 __FUNCTION__, mId);
668 } else {
669 mState = ACTIVE;
670 }
671
672cleanUpBuffers:
673 for (int i = 0; i < bufferIdx; i++) {
674 res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
675 anwBuffers[i]);
676 if (res != OK) {
677 ALOGE("%s: Unable to cancel buffer %d after registration",
678 __FUNCTION__, i);
679 }
680 }
681 delete anwBuffers;
682 delete buffers;
683
684 return res;
685}
686
687status_t Camera2Device::StreamAdapter::disconnect() {
688 status_t res;
689 if (mState >= ALLOCATED) {
690 res = mDevice->ops->release_stream(mDevice, mId);
691 if (res != OK) {
692 ALOGE("%s: Unable to release stream %d",
693 __FUNCTION__, mId);
694 return res;
695 }
696 }
697 if (mState >= CONNECTED) {
698 res = native_window_api_disconnect(mConsumerInterface.get(),
699 NATIVE_WINDOW_API_CAMERA);
700 if (res != OK) {
701 ALOGE("%s: Unable to disconnect stream %d from native window",
702 __FUNCTION__, mId);
703 return res;
704 }
705 }
706 mId = -1;
707 mState = DISCONNECTED;
708 return OK;
709}
710
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700711const camera2_stream_ops *Camera2Device::StreamAdapter::getStreamOps() {
712 return static_cast<camera2_stream_ops *>(this);
713}
714
715ANativeWindow* Camera2Device::StreamAdapter::toANW(
716 const camera2_stream_ops_t *w) {
717 return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get();
718}
719
720int Camera2Device::StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w,
721 buffer_handle_t** buffer) {
722 int res;
723 int state = static_cast<const StreamAdapter*>(w)->mState;
724 if (state != ACTIVE) {
725 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
726 return INVALID_OPERATION;
727 }
728
729 ANativeWindow *a = toANW(w);
730 ANativeWindowBuffer* anb;
731 res = a->dequeueBuffer(a, &anb);
732 if (res != OK) return res;
733 res = a->lockBuffer(a, anb);
734 if (res != OK) return res;
735
736 *buffer = &(anb->handle);
737 ALOGV("%s: Buffer %p", __FUNCTION__, *buffer);
738 return res;
739}
740
741int Camera2Device::StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w,
742 int64_t timestamp,
743 buffer_handle_t* buffer) {
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700744 const StreamAdapter *stream = static_cast<const StreamAdapter*>(w);
745 ALOGV("%s: Stream %d: Buffer %p captured at %lld ns",
746 __FUNCTION__, stream->mId, buffer, timestamp);
747 int state = stream->mState;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700748 if (state != ACTIVE) {
749 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
750 return INVALID_OPERATION;
751 }
752 ANativeWindow *a = toANW(w);
753 status_t err;
754 err = native_window_set_buffers_timestamp(a, timestamp);
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700755 if (err != OK) {
756 ALOGE("%s: Error setting timestamp on native window: %s (%d)",
757 __FUNCTION__, strerror(-err), err);
758 return err;
759 }
760 err = a->queueBuffer(a,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700761 container_of(buffer, ANativeWindowBuffer, handle));
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700762 if (err != OK) {
763 ALOGE("%s: Error queueing buffer to native window: %s (%d)",
764 __FUNCTION__, strerror(-err), err);
765 }
766 return err;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700767}
768
769int Camera2Device::StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w,
770 buffer_handle_t* buffer) {
771 int state = static_cast<const StreamAdapter*>(w)->mState;
772 if (state != ACTIVE) {
773 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
774 return INVALID_OPERATION;
775 }
776 ANativeWindow *a = toANW(w);
777 return a->cancelBuffer(a,
778 container_of(buffer, ANativeWindowBuffer, handle));
779}
780
781int Camera2Device::StreamAdapter::set_crop(const camera2_stream_ops_t* w,
782 int left, int top, int right, int bottom) {
783 int state = static_cast<const StreamAdapter*>(w)->mState;
784 if (state != ACTIVE) {
785 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
786 return INVALID_OPERATION;
787 }
788 ANativeWindow *a = toANW(w);
789 android_native_rect_t crop = { left, top, right, bottom };
790 return native_window_set_crop(a, &crop);
791}
792
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700793
794}; // namespace android