blob: 718d42b0dc2a2641a8903dd3c5ec6ef4c907c07f [file] [log] [blame]
Alex Ray7ee0b7a2012-11-06 00:12:49 -08001/*
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#include <cstdlib>
18#include <pthread.h>
Alex Raya0ed4be2013-02-25 15:02:16 -080019#include <hardware/camera3.h>
Alex Ray083315c2013-04-26 19:32:29 -070020#include <sync/sync.h>
Alex Raybfcbd952013-03-20 13:20:02 -070021#include <system/camera_metadata.h>
Alex Raya0ed4be2013-02-25 15:02:16 -080022#include "CameraHAL.h"
Alex Raybcaf7882013-02-28 16:04:35 -080023#include "Stream.h"
Alex Ray7ee0b7a2012-11-06 00:12:49 -080024
Alex Rayed6b8a72012-12-27 10:42:22 -080025//#define LOG_NDEBUG 0
Alex Ray7ee0b7a2012-11-06 00:12:49 -080026#define LOG_TAG "Camera"
27#include <cutils/log.h>
28
Alex Rayed6b8a72012-12-27 10:42:22 -080029#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
30#include <cutils/trace.h>
Alex Rayc16e56d2013-04-29 12:24:49 -070031#include "ScopedTrace.h"
Alex Rayed6b8a72012-12-27 10:42:22 -080032
Alex Ray7ee0b7a2012-11-06 00:12:49 -080033#include "Camera.h"
34
Alex Ray083315c2013-04-26 19:32:29 -070035#define CAMERA_SYNC_TIMEOUT 5000 // in msecs
36
Alex Ray7ee0b7a2012-11-06 00:12:49 -080037namespace default_camera_hal {
38
39extern "C" {
40// Shim passed to the framework to close an opened device.
41static int close_device(hw_device_t* dev)
42{
Alex Raya0ed4be2013-02-25 15:02:16 -080043 camera3_device_t* cam_dev = reinterpret_cast<camera3_device_t*>(dev);
Alex Ray7ee0b7a2012-11-06 00:12:49 -080044 Camera* cam = static_cast<Camera*>(cam_dev->priv);
45 return cam->close();
46}
47} // extern "C"
48
Alex Raya0ed4be2013-02-25 15:02:16 -080049Camera::Camera(int id)
50 : mId(id),
51 mBusy(false),
Alex Raybcaf7882013-02-28 16:04:35 -080052 mCallbackOps(NULL),
53 mStreams(NULL),
Alex Raybfcbd952013-03-20 13:20:02 -070054 mNumStreams(0),
55 mSettings(NULL)
Alex Ray7ee0b7a2012-11-06 00:12:49 -080056{
57 pthread_mutex_init(&mMutex,
58 NULL); // No pthread mutex attributes.
59
Alex Raya0ed4be2013-02-25 15:02:16 -080060 memset(&mDevice, 0, sizeof(mDevice));
Alex Ray7ee0b7a2012-11-06 00:12:49 -080061 mDevice.common.tag = HARDWARE_DEVICE_TAG;
Alex Ray7ee0b7a2012-11-06 00:12:49 -080062 mDevice.common.close = close_device;
Alex Raya0ed4be2013-02-25 15:02:16 -080063 mDevice.ops = const_cast<camera3_device_ops_t*>(&sOps);
Alex Ray7ee0b7a2012-11-06 00:12:49 -080064 mDevice.priv = this;
65}
66
67Camera::~Camera()
68{
69}
70
Alex Raya0ed4be2013-02-25 15:02:16 -080071int Camera::open(const hw_module_t *module, hw_device_t **device)
Alex Ray7ee0b7a2012-11-06 00:12:49 -080072{
Alex Raya0ed4be2013-02-25 15:02:16 -080073 ALOGI("%s:%d: Opening camera device", __func__, mId);
Alex Rayc16e56d2013-04-29 12:24:49 -070074 CAMTRACE_CALL();
Alex Ray7ee0b7a2012-11-06 00:12:49 -080075 pthread_mutex_lock(&mMutex);
76 if (mBusy) {
77 pthread_mutex_unlock(&mMutex);
Alex Raya0ed4be2013-02-25 15:02:16 -080078 ALOGE("%s:%d: Error! Camera device already opened", __func__, mId);
Alex Ray7ee0b7a2012-11-06 00:12:49 -080079 return -EBUSY;
80 }
81
82 // TODO: open camera dev nodes, etc
83 mBusy = true;
Alex Raya0ed4be2013-02-25 15:02:16 -080084 mDevice.common.module = const_cast<hw_module_t*>(module);
85 *device = &mDevice.common;
Alex Ray7ee0b7a2012-11-06 00:12:49 -080086
87 pthread_mutex_unlock(&mMutex);
88 return 0;
89}
90
91int Camera::close()
92{
Alex Raya0ed4be2013-02-25 15:02:16 -080093 ALOGI("%s:%d: Closing camera device", __func__, mId);
Alex Rayc16e56d2013-04-29 12:24:49 -070094 CAMTRACE_CALL();
Alex Ray7ee0b7a2012-11-06 00:12:49 -080095 pthread_mutex_lock(&mMutex);
96 if (!mBusy) {
97 pthread_mutex_unlock(&mMutex);
Alex Raya0ed4be2013-02-25 15:02:16 -080098 ALOGE("%s:%d: Error! Camera device not open", __func__, mId);
Alex Ray7ee0b7a2012-11-06 00:12:49 -080099 return -EINVAL;
100 }
101
102 // TODO: close camera dev nodes, etc
103 mBusy = false;
104
105 pthread_mutex_unlock(&mMutex);
106 return 0;
107}
108
Alex Raya0ed4be2013-02-25 15:02:16 -0800109int Camera::initialize(const camera3_callback_ops_t *callback_ops)
Alex Ray7ee0b7a2012-11-06 00:12:49 -0800110{
Alex Raya0ed4be2013-02-25 15:02:16 -0800111 ALOGV("%s:%d: callback_ops=%p", __func__, mId, callback_ops);
112 mCallbackOps = callback_ops;
Alex Ray7ee0b7a2012-11-06 00:12:49 -0800113 return 0;
114}
115
Alex Raybcaf7882013-02-28 16:04:35 -0800116int Camera::configureStreams(camera3_stream_configuration_t *stream_config)
Alex Ray7ee0b7a2012-11-06 00:12:49 -0800117{
Alex Raybcaf7882013-02-28 16:04:35 -0800118 camera3_stream_t *astream;
119 Stream **newStreams = NULL;
120
121 CAMTRACE_CALL();
122 ALOGV("%s:%d: stream_config=%p", __func__, mId, stream_config);
123
124 if (stream_config == NULL) {
125 ALOGE("%s:%d: NULL stream configuration array", __func__, mId);
126 return -EINVAL;
127 }
128 if (stream_config->num_streams == 0) {
129 ALOGE("%s:%d: Empty stream configuration array", __func__, mId);
130 return -EINVAL;
131 }
132
133 // Create new stream array
134 newStreams = new Stream*[stream_config->num_streams];
135 ALOGV("%s:%d: Number of Streams: %d", __func__, mId,
136 stream_config->num_streams);
137
138 pthread_mutex_lock(&mMutex);
139
140 // Mark all current streams unused for now
141 for (int i = 0; i < mNumStreams; i++)
142 mStreams[i]->mReuse = false;
143 // Fill new stream array with reused streams and new streams
144 for (int i = 0; i < stream_config->num_streams; i++) {
145 astream = stream_config->streams[i];
146 if (astream->max_buffers > 0)
147 newStreams[i] = reuseStream(astream);
148 else
149 newStreams[i] = new Stream(mId, astream);
150
151 if (newStreams[i] == NULL) {
152 ALOGE("%s:%d: Error processing stream %d", __func__, mId, i);
153 goto err_out;
154 }
155 astream->priv = newStreams[i];
156 }
157
158 // Verify the set of streams in aggregate
159 if (!isValidStreamSet(newStreams, stream_config->num_streams)) {
160 ALOGE("%s:%d: Invalid stream set", __func__, mId);
161 goto err_out;
162 }
163
164 // Set up all streams (calculate usage/max_buffers for each)
165 setupStreams(newStreams, stream_config->num_streams);
166
167 // Destroy all old streams and replace stream array with new one
168 destroyStreams(mStreams, mNumStreams);
169 mStreams = newStreams;
170 mNumStreams = stream_config->num_streams;
171
Alex Raybfcbd952013-03-20 13:20:02 -0700172 // Clear out last seen settings metadata
173 setSettings(NULL);
174
Alex Raybcaf7882013-02-28 16:04:35 -0800175 pthread_mutex_unlock(&mMutex);
Alex Raya0ed4be2013-02-25 15:02:16 -0800176 return 0;
Alex Raybcaf7882013-02-28 16:04:35 -0800177
178err_out:
179 // Clean up temporary streams, preserve existing mStreams/mNumStreams
180 destroyStreams(newStreams, stream_config->num_streams);
181 pthread_mutex_unlock(&mMutex);
182 return -EINVAL;
183}
184
185void Camera::destroyStreams(Stream **streams, int count)
186{
187 if (streams == NULL)
188 return;
189 for (int i = 0; i < count; i++) {
190 // Only destroy streams that weren't reused
191 if (streams[i] != NULL && !streams[i]->mReuse)
192 delete streams[i];
193 }
194 delete [] streams;
195}
196
197Stream *Camera::reuseStream(camera3_stream_t *astream)
198{
199 Stream *priv = reinterpret_cast<Stream*>(astream->priv);
200 // Verify the re-used stream's parameters match
201 if (!priv->isValidReuseStream(mId, astream)) {
202 ALOGE("%s:%d: Mismatched parameter in reused stream", __func__, mId);
203 return NULL;
204 }
205 // Mark stream to be reused
206 priv->mReuse = true;
207 return priv;
208}
209
210bool Camera::isValidStreamSet(Stream **streams, int count)
211{
212 int inputs = 0;
213 int outputs = 0;
214
215 if (streams == NULL) {
216 ALOGE("%s:%d: NULL stream configuration streams", __func__, mId);
217 return false;
218 }
219 if (count == 0) {
220 ALOGE("%s:%d: Zero count stream configuration streams", __func__, mId);
221 return false;
222 }
223 // Validate there is at most one input stream and at least one output stream
224 for (int i = 0; i < count; i++) {
225 // A stream may be both input and output (bidirectional)
226 if (streams[i]->isInputType())
227 inputs++;
228 if (streams[i]->isOutputType())
229 outputs++;
230 }
231 if (outputs < 1) {
232 ALOGE("%s:%d: Stream config must have >= 1 output", __func__, mId);
233 return false;
234 }
235 if (inputs > 1) {
236 ALOGE("%s:%d: Stream config must have <= 1 input", __func__, mId);
237 return false;
238 }
239 // TODO: check for correct number of Bayer/YUV/JPEG/Encoder streams
240 return true;
241}
242
243void Camera::setupStreams(Stream **streams, int count)
244{
245 /*
246 * This is where the HAL has to decide internally how to handle all of the
247 * streams, and then produce usage and max_buffer values for each stream.
248 * Note, the stream array has been checked before this point for ALL invalid
249 * conditions, so it must find a successful configuration for this stream
250 * array. The HAL may not return an error from this point.
251 *
252 * In this demo HAL, we just set all streams to be the same dummy values;
253 * real implementations will want to avoid USAGE_SW_{READ|WRITE}_OFTEN.
254 */
255 for (int i = 0; i < count; i++) {
256 uint32_t usage = 0;
257
258 if (streams[i]->isOutputType())
259 usage |= GRALLOC_USAGE_SW_WRITE_OFTEN |
260 GRALLOC_USAGE_HW_CAMERA_WRITE;
261 if (streams[i]->isInputType())
262 usage |= GRALLOC_USAGE_SW_READ_OFTEN |
263 GRALLOC_USAGE_HW_CAMERA_READ;
264
265 streams[i]->setUsage(usage);
266 streams[i]->setMaxBuffers(1);
267 }
Alex Raya0ed4be2013-02-25 15:02:16 -0800268}
269
270int Camera::registerStreamBuffers(const camera3_stream_buffer_set_t *buf_set)
271{
272 ALOGV("%s:%d: buffer_set=%p", __func__, mId, buf_set);
Alex Ray8a8f86b2013-03-01 01:32:21 -0800273 if (buf_set == NULL) {
274 ALOGE("%s:%d: NULL buffer set", __func__, mId);
275 return -EINVAL;
276 }
277 if (buf_set->stream == NULL) {
278 ALOGE("%s:%d: NULL stream handle", __func__, mId);
279 return -EINVAL;
280 }
281 Stream *stream = reinterpret_cast<Stream*>(buf_set->stream->priv);
282 return stream->registerBuffers(buf_set);
Alex Raya0ed4be2013-02-25 15:02:16 -0800283}
284
285const camera_metadata_t* Camera::constructDefaultRequestSettings(int type)
286{
287 ALOGV("%s:%d: type=%d", __func__, mId, type);
288 // TODO: return statically built default request
289 return NULL;
290}
291
292int Camera::processCaptureRequest(camera3_capture_request_t *request)
293{
Alex Ray083315c2013-04-26 19:32:29 -0700294 camera3_capture_result result;
295
Alex Raya0ed4be2013-02-25 15:02:16 -0800296 ALOGV("%s:%d: request=%p", __func__, mId, request);
Alex Rayc16e56d2013-04-29 12:24:49 -0700297 CAMTRACE_CALL();
Alex Raya0ed4be2013-02-25 15:02:16 -0800298
299 if (request == NULL) {
300 ALOGE("%s:%d: NULL request recieved", __func__, mId);
Alex Raya0ed4be2013-02-25 15:02:16 -0800301 return -EINVAL;
Alex Ray7ee0b7a2012-11-06 00:12:49 -0800302 }
303
Alex Raybfcbd952013-03-20 13:20:02 -0700304 ALOGV("%s:%d: Request Frame:%d Settings:%p", __func__, mId,
305 request->frame_number, request->settings);
306
307 // NULL indicates use last settings
308 if (request->settings == NULL) {
309 if (mSettings == NULL) {
310 ALOGE("%s:%d: NULL settings without previous set Frame:%d Req:%p",
311 __func__, mId, request->frame_number, request);
312 return -EINVAL;
313 }
314 } else {
315 setSettings(request->settings);
316 }
317
Alex Ray11bbeef2013-04-26 14:47:08 -0700318 if (request->input_buffer != NULL) {
319 ALOGV("%s:%d: Reprocessing input buffer %p", __func__, mId,
320 request->input_buffer);
321
322 if (!isValidReprocessSettings(request->settings)) {
323 ALOGE("%s:%d: Invalid settings for reprocess request: %p",
324 __func__, mId, request->settings);
325 return -EINVAL;
326 }
327 } else {
328 ALOGV("%s:%d: Capturing new frame.", __func__, mId);
329
330 if (!isValidCaptureSettings(request->settings)) {
331 ALOGE("%s:%d: Invalid settings for capture request: %p",
332 __func__, mId, request->settings);
333 return -EINVAL;
334 }
335 }
336
Alex Ray083315c2013-04-26 19:32:29 -0700337 if (request->num_output_buffers <= 0) {
338 ALOGE("%s:%d: Invalid number of output buffers: %d", __func__, mId,
339 request->num_output_buffers);
340 return -EINVAL;
341 }
342 result.num_output_buffers = request->num_output_buffers;
343 result.output_buffers = new camera3_stream_buffer_t[result.num_output_buffers];
344 for (unsigned int i = 0; i < request->num_output_buffers; i++) {
345 int res = processCaptureBuffer(&request->output_buffers[i],
346 const_cast<camera3_stream_buffer_t*>(&result.output_buffers[i]));
347 if (res)
348 goto err_out;
349 }
350
351 result.frame_number = request->frame_number;
352 // TODO: return actual captured/reprocessed settings
353 result.result = request->settings;
354 // TODO: asynchronously return results
355 mCallbackOps->process_capture_result(mCallbackOps, &result);
356
Alex Raya0ed4be2013-02-25 15:02:16 -0800357 return 0;
Alex Ray083315c2013-04-26 19:32:29 -0700358
359err_out:
360 delete [] result.output_buffers;
361 // TODO: this should probably be a total device failure; transient for now
362 return -EINVAL;
Alex Ray7ee0b7a2012-11-06 00:12:49 -0800363}
364
Alex Raybfcbd952013-03-20 13:20:02 -0700365void Camera::setSettings(const camera_metadata_t *new_settings)
366{
367 if (mSettings != NULL) {
368 free_camera_metadata(mSettings);
369 mSettings = NULL;
370 }
371
372 if (new_settings != NULL)
373 mSettings = clone_camera_metadata(new_settings);
374}
375
Alex Ray11bbeef2013-04-26 14:47:08 -0700376bool Camera::isValidCaptureSettings(const camera_metadata_t *settings)
377{
378 // TODO: reject settings that cannot be captured
379 return true;
380}
381
382bool Camera::isValidReprocessSettings(const camera_metadata_t *settings)
383{
384 // TODO: reject settings that cannot be reprocessed
385 // input buffers unimplemented, use this to reject reprocessing requests
386 ALOGE("%s:%d: Input buffer reprocessing not implemented", __func__, mId);
387 return false;
388}
389
Alex Ray083315c2013-04-26 19:32:29 -0700390int Camera::processCaptureBuffer(const camera3_stream_buffer_t *in,
391 camera3_stream_buffer_t *out)
392{
393 int res = sync_wait(in->acquire_fence, CAMERA_SYNC_TIMEOUT);
394 if (res == -ETIME) {
395 ALOGE("%s:%d: Timeout waiting on buffer acquire fence", __func__, mId);
396 return res;
397 } else if (res) {
398 ALOGE("%s:%d: Error waiting on buffer acquire fence: %s(%d)",
399 __func__, mId, strerror(-res), res);
400 return res;
401 }
402
403 out->stream = in->stream;
404 out->buffer = in->buffer;
405 out->status = CAMERA3_BUFFER_STATUS_OK;
406 // TODO: use driver-backed release fences
407 out->acquire_fence = -1;
408 out->release_fence = -1;
409
410 // TODO: lock and software-paint buffer
411 return 0;
412}
413
Alex Raya0ed4be2013-02-25 15:02:16 -0800414void Camera::getMetadataVendorTagOps(vendor_tag_query_ops_t *ops)
415{
416 ALOGV("%s:%d: ops=%p", __func__, mId, ops);
417 // TODO: return vendor tag ops
418}
419
420void Camera::dump(int fd)
421{
Alex Rayaf3a4612013-04-29 14:16:10 -0700422 ALOGV("%s:%d: Dumping to fd %d", __func__, mId, fd);
Alex Raya0ed4be2013-02-25 15:02:16 -0800423 // TODO: dprintf all relevant state to fd
424}
425
426extern "C" {
427// Get handle to camera from device priv data
428static Camera *camdev_to_camera(const camera3_device_t *dev)
429{
430 return reinterpret_cast<Camera*>(dev->priv);
431}
432
433static int initialize(const camera3_device_t *dev,
434 const camera3_callback_ops_t *callback_ops)
435{
436 return camdev_to_camera(dev)->initialize(callback_ops);
437}
438
439static int configure_streams(const camera3_device_t *dev,
440 camera3_stream_configuration_t *stream_list)
441{
442 return camdev_to_camera(dev)->configureStreams(stream_list);
443}
444
445static int register_stream_buffers(const camera3_device_t *dev,
446 const camera3_stream_buffer_set_t *buffer_set)
447{
448 return camdev_to_camera(dev)->registerStreamBuffers(buffer_set);
449}
450
451static const camera_metadata_t *construct_default_request_settings(
452 const camera3_device_t *dev, int type)
453{
454 return camdev_to_camera(dev)->constructDefaultRequestSettings(type);
455}
456
457static int process_capture_request(const camera3_device_t *dev,
458 camera3_capture_request_t *request)
459{
460 return camdev_to_camera(dev)->processCaptureRequest(request);
461}
462
463static void get_metadata_vendor_tag_ops(const camera3_device_t *dev,
464 vendor_tag_query_ops_t *ops)
465{
466 camdev_to_camera(dev)->getMetadataVendorTagOps(ops);
467}
468
469static void dump(const camera3_device_t *dev, int fd)
470{
471 camdev_to_camera(dev)->dump(fd);
472}
473} // extern "C"
474
475const camera3_device_ops_t Camera::sOps = {
476 .initialize = default_camera_hal::initialize,
477 .configure_streams = default_camera_hal::configure_streams,
478 .register_stream_buffers = default_camera_hal::register_stream_buffers,
479 .construct_default_request_settings =
480 default_camera_hal::construct_default_request_settings,
481 .process_capture_request = default_camera_hal::process_capture_request,
482 .get_metadata_vendor_tag_ops =
483 default_camera_hal::get_metadata_vendor_tag_ops,
484 .dump = default_camera_hal::dump
485};
486
Alex Ray7ee0b7a2012-11-06 00:12:49 -0800487} // namespace default_camera_hal