Camera.cpp revision 083315c85baf28098637684d2307ee8d4df337c6
1/*
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>
19#include <hardware/camera3.h>
20#include <sync/sync.h>
21#include <system/camera_metadata.h>
22#include "CameraHAL.h"
23#include "Stream.h"
24
25//#define LOG_NDEBUG 0
26#define LOG_TAG "Camera"
27#include <cutils/log.h>
28
29#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
30#include <cutils/trace.h>
31#include "ScopedTrace.h"
32
33#include "Camera.h"
34
35#define CAMERA_SYNC_TIMEOUT 5000 // in msecs
36
37namespace 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{
43    camera3_device_t* cam_dev = reinterpret_cast<camera3_device_t*>(dev);
44    Camera* cam = static_cast<Camera*>(cam_dev->priv);
45    return cam->close();
46}
47} // extern "C"
48
49Camera::Camera(int id)
50  : mId(id),
51    mBusy(false),
52    mCallbackOps(NULL),
53    mStreams(NULL),
54    mNumStreams(0),
55    mSettings(NULL)
56{
57    pthread_mutex_init(&mMutex,
58                       NULL); // No pthread mutex attributes.
59
60    memset(&mDevice, 0, sizeof(mDevice));
61    mDevice.common.tag    = HARDWARE_DEVICE_TAG;
62    mDevice.common.close  = close_device;
63    mDevice.ops           = const_cast<camera3_device_ops_t*>(&sOps);
64    mDevice.priv          = this;
65}
66
67Camera::~Camera()
68{
69}
70
71int Camera::open(const hw_module_t *module, hw_device_t **device)
72{
73    ALOGI("%s:%d: Opening camera device", __func__, mId);
74    CAMTRACE_CALL();
75    pthread_mutex_lock(&mMutex);
76    if (mBusy) {
77        pthread_mutex_unlock(&mMutex);
78        ALOGE("%s:%d: Error! Camera device already opened", __func__, mId);
79        return -EBUSY;
80    }
81
82    // TODO: open camera dev nodes, etc
83    mBusy = true;
84    mDevice.common.module = const_cast<hw_module_t*>(module);
85    *device = &mDevice.common;
86
87    pthread_mutex_unlock(&mMutex);
88    return 0;
89}
90
91int Camera::close()
92{
93    ALOGI("%s:%d: Closing camera device", __func__, mId);
94    CAMTRACE_CALL();
95    pthread_mutex_lock(&mMutex);
96    if (!mBusy) {
97        pthread_mutex_unlock(&mMutex);
98        ALOGE("%s:%d: Error! Camera device not open", __func__, mId);
99        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
109int Camera::initialize(const camera3_callback_ops_t *callback_ops)
110{
111    ALOGV("%s:%d: callback_ops=%p", __func__, mId, callback_ops);
112    mCallbackOps = callback_ops;
113    return 0;
114}
115
116int Camera::configureStreams(camera3_stream_configuration_t *stream_config)
117{
118    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
172    // Clear out last seen settings metadata
173    setSettings(NULL);
174
175    pthread_mutex_unlock(&mMutex);
176    return 0;
177
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    }
268}
269
270int Camera::registerStreamBuffers(const camera3_stream_buffer_set_t *buf_set)
271{
272    ALOGV("%s:%d: buffer_set=%p", __func__, mId, buf_set);
273    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);
283}
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{
294    camera3_capture_result result;
295
296    ALOGV("%s:%d: request=%p", __func__, mId, request);
297    CAMTRACE_CALL();
298
299    if (request == NULL) {
300        ALOGE("%s:%d: NULL request recieved", __func__, mId);
301        return -EINVAL;
302    }
303
304    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
318    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
337    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
357    return 0;
358
359err_out:
360    delete [] result.output_buffers;
361    // TODO: this should probably be a total device failure; transient for now
362    return -EINVAL;
363}
364
365void 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
376bool 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
390int 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
414void 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{
422    ALOGV("%s:%d: Dumping to fd %d", __func__, mId, fd);
423    // 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
487} // namespace default_camera_hal
488