summaryrefslogtreecommitdiffstats
path: root/modules/camera
diff options
context:
space:
mode:
authorAlex Ray <aray@google.com>2013-05-13 19:47:22 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-05-13 19:47:22 +0000
commite0bd66511a68933eef3347d5e581e043d7eddcb8 (patch)
tree2c0c6eb21ee958b71f1e7c602b6f9c52fd33d15e /modules/camera
parentbb884457df1da8886ca05263be3303180805937a (diff)
parentbcaf788434b0f4fcc4f194ca01d94cd59eb912a9 (diff)
downloadhardware_libhardware-e0bd66511a68933eef3347d5e581e043d7eddcb8.zip
hardware_libhardware-e0bd66511a68933eef3347d5e581e043d7eddcb8.tar.gz
hardware_libhardware-e0bd66511a68933eef3347d5e581e043d7eddcb8.tar.bz2
Merge "modules: camera: Add Streams"
Diffstat (limited to 'modules/camera')
-rw-r--r--modules/camera/Android.mk1
-rw-r--r--modules/camera/Camera.cpp155
-rw-r--r--modules/camera/Camera.h14
-rw-r--r--modules/camera/Stream.cpp129
-rw-r--r--modules/camera/Stream.h69
5 files changed, 364 insertions, 4 deletions
diff --git a/modules/camera/Android.mk b/modules/camera/Android.mk
index eebffc1..823fe17 100644
--- a/modules/camera/Android.mk
+++ b/modules/camera/Android.mk
@@ -26,6 +26,7 @@ LOCAL_C_INCLUDES += \
LOCAL_SRC_FILES := \
CameraHAL.cpp \
Camera.cpp \
+ Stream.cpp \
LOCAL_SHARED_LIBRARIES := \
libcamera_metadata \
diff --git a/modules/camera/Camera.cpp b/modules/camera/Camera.cpp
index d477ef6..b06f65d 100644
--- a/modules/camera/Camera.cpp
+++ b/modules/camera/Camera.cpp
@@ -18,6 +18,7 @@
#include <pthread.h>
#include <hardware/camera3.h>
#include "CameraHAL.h"
+#include "Stream.h"
//#define LOG_NDEBUG 0
#define LOG_TAG "Camera"
@@ -44,7 +45,9 @@ static int close_device(hw_device_t* dev)
Camera::Camera(int id)
: mId(id),
mBusy(false),
- mCallbackOps(NULL)
+ mCallbackOps(NULL),
+ mStreams(NULL),
+ mNumStreams(0)
{
pthread_mutex_init(&mMutex,
NULL); // No pthread mutex attributes.
@@ -105,11 +108,155 @@ int Camera::initialize(const camera3_callback_ops_t *callback_ops)
return 0;
}
-int Camera::configureStreams(camera3_stream_configuration_t *stream_list)
+int Camera::configureStreams(camera3_stream_configuration_t *stream_config)
{
- ALOGV("%s:%d: stream_list=%p", __func__, mId, stream_list);
- // TODO: validate input, create internal stream representations
+ camera3_stream_t *astream;
+ Stream **newStreams = NULL;
+
+ CAMTRACE_CALL();
+ ALOGV("%s:%d: stream_config=%p", __func__, mId, stream_config);
+
+ if (stream_config == NULL) {
+ ALOGE("%s:%d: NULL stream configuration array", __func__, mId);
+ return -EINVAL;
+ }
+ if (stream_config->num_streams == 0) {
+ ALOGE("%s:%d: Empty stream configuration array", __func__, mId);
+ return -EINVAL;
+ }
+
+ // Create new stream array
+ newStreams = new Stream*[stream_config->num_streams];
+ ALOGV("%s:%d: Number of Streams: %d", __func__, mId,
+ stream_config->num_streams);
+
+ pthread_mutex_lock(&mMutex);
+
+ // Mark all current streams unused for now
+ for (int i = 0; i < mNumStreams; i++)
+ mStreams[i]->mReuse = false;
+ // Fill new stream array with reused streams and new streams
+ for (int i = 0; i < stream_config->num_streams; i++) {
+ astream = stream_config->streams[i];
+ if (astream->max_buffers > 0)
+ newStreams[i] = reuseStream(astream);
+ else
+ newStreams[i] = new Stream(mId, astream);
+
+ if (newStreams[i] == NULL) {
+ ALOGE("%s:%d: Error processing stream %d", __func__, mId, i);
+ goto err_out;
+ }
+ astream->priv = newStreams[i];
+ }
+
+ // Verify the set of streams in aggregate
+ if (!isValidStreamSet(newStreams, stream_config->num_streams)) {
+ ALOGE("%s:%d: Invalid stream set", __func__, mId);
+ goto err_out;
+ }
+
+ // Set up all streams (calculate usage/max_buffers for each)
+ setupStreams(newStreams, stream_config->num_streams);
+
+ // Destroy all old streams and replace stream array with new one
+ destroyStreams(mStreams, mNumStreams);
+ mStreams = newStreams;
+ mNumStreams = stream_config->num_streams;
+
+ pthread_mutex_unlock(&mMutex);
return 0;
+
+err_out:
+ // Clean up temporary streams, preserve existing mStreams/mNumStreams
+ destroyStreams(newStreams, stream_config->num_streams);
+ pthread_mutex_unlock(&mMutex);
+ return -EINVAL;
+}
+
+void Camera::destroyStreams(Stream **streams, int count)
+{
+ if (streams == NULL)
+ return;
+ for (int i = 0; i < count; i++) {
+ // Only destroy streams that weren't reused
+ if (streams[i] != NULL && !streams[i]->mReuse)
+ delete streams[i];
+ }
+ delete [] streams;
+}
+
+Stream *Camera::reuseStream(camera3_stream_t *astream)
+{
+ Stream *priv = reinterpret_cast<Stream*>(astream->priv);
+ // Verify the re-used stream's parameters match
+ if (!priv->isValidReuseStream(mId, astream)) {
+ ALOGE("%s:%d: Mismatched parameter in reused stream", __func__, mId);
+ return NULL;
+ }
+ // Mark stream to be reused
+ priv->mReuse = true;
+ return priv;
+}
+
+bool Camera::isValidStreamSet(Stream **streams, int count)
+{
+ int inputs = 0;
+ int outputs = 0;
+
+ if (streams == NULL) {
+ ALOGE("%s:%d: NULL stream configuration streams", __func__, mId);
+ return false;
+ }
+ if (count == 0) {
+ ALOGE("%s:%d: Zero count stream configuration streams", __func__, mId);
+ return false;
+ }
+ // Validate there is at most one input stream and at least one output stream
+ for (int i = 0; i < count; i++) {
+ // A stream may be both input and output (bidirectional)
+ if (streams[i]->isInputType())
+ inputs++;
+ if (streams[i]->isOutputType())
+ outputs++;
+ }
+ if (outputs < 1) {
+ ALOGE("%s:%d: Stream config must have >= 1 output", __func__, mId);
+ return false;
+ }
+ if (inputs > 1) {
+ ALOGE("%s:%d: Stream config must have <= 1 input", __func__, mId);
+ return false;
+ }
+ // TODO: check for correct number of Bayer/YUV/JPEG/Encoder streams
+ return true;
+}
+
+void Camera::setupStreams(Stream **streams, int count)
+{
+ /*
+ * This is where the HAL has to decide internally how to handle all of the
+ * streams, and then produce usage and max_buffer values for each stream.
+ * Note, the stream array has been checked before this point for ALL invalid
+ * conditions, so it must find a successful configuration for this stream
+ * array. The HAL may not return an error from this point.
+ *
+ * In this demo HAL, we just set all streams to be the same dummy values;
+ * real implementations will want to avoid USAGE_SW_{READ|WRITE}_OFTEN.
+ */
+ for (int i = 0; i < count; i++) {
+ uint32_t usage = 0;
+
+ if (streams[i]->isOutputType())
+ usage |= GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_CAMERA_WRITE;
+ if (streams[i]->isInputType())
+ usage |= GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_HW_CAMERA_READ;
+
+ streams[i]->setUsage(usage);
+ streams[i]->setMaxBuffers(1);
+ }
}
int Camera::registerStreamBuffers(const camera3_stream_buffer_set_t *buf_set)
diff --git a/modules/camera/Camera.h b/modules/camera/Camera.h
index f2ad093..c43e207 100644
--- a/modules/camera/Camera.h
+++ b/modules/camera/Camera.h
@@ -20,6 +20,7 @@
#include <pthread.h>
#include <hardware/hardware.h>
#include <hardware/camera3.h>
+#include "Stream.h"
namespace default_camera_hal {
// Camera represents a physical camera on a device.
@@ -50,6 +51,15 @@ class Camera {
camera3_device_t mDevice;
private:
+ // Reuse a stream already created by this device
+ Stream *reuseStream(camera3_stream_t *astream);
+ // Destroy all streams in a stream array, and the array itself
+ void destroyStreams(Stream **array, int count);
+ // Verify a set of streams is valid in aggregate
+ bool isValidStreamSet(Stream **array, int count);
+ // Calculate usage and max_bufs of each stream
+ void setupStreams(Stream **array, int count);
+
// Identifier used by framework to distinguish cameras
const int mId;
// Busy flag indicates camera is in use
@@ -60,6 +70,10 @@ class Camera {
const camera3_callback_ops_t *mCallbackOps;
// Lock protecting the Camera object for modifications
pthread_mutex_t mMutex;
+ // Array of handles to streams currently in use by the device
+ Stream **mStreams;
+ // Number of streams in mStreams
+ int mNumStreams;
};
} // namespace default_camera_hal
diff --git a/modules/camera/Stream.cpp b/modules/camera/Stream.cpp
new file mode 100644
index 0000000..08ae159
--- /dev/null
+++ b/modules/camera/Stream.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pthread.h>
+#include <hardware/camera3.h>
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Stream"
+#include <cutils/log.h>
+
+#define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+#include <cutils/trace.h>
+#include "ScopedTrace.h"
+
+#include "Stream.h"
+
+namespace default_camera_hal {
+
+Stream::Stream(int id, camera3_stream_t *s)
+ : mReuse(false),
+ mId(id),
+ mStream(s),
+ mType(s->stream_type),
+ mWidth(s->width),
+ mHeight(s->height),
+ mFormat(s->format),
+ mUsage(0),
+ mMaxBuffers(0),
+ mRegistered(false)
+{
+ // NULL (default) pthread mutex attributes
+ pthread_mutex_init(&mMutex, NULL);
+}
+
+Stream::~Stream()
+{
+ // TODO: unregister buffers from hw
+}
+
+void Stream::setUsage(uint32_t usage)
+{
+ pthread_mutex_lock(&mMutex);
+ if (usage != mUsage) {
+ mUsage = usage;
+ mRegistered = false;
+ // TODO: unregister buffers from hw
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+void Stream::setMaxBuffers(uint32_t max_buffers)
+{
+ pthread_mutex_lock(&mMutex);
+ if (max_buffers != mMaxBuffers) {
+ mMaxBuffers = max_buffers;
+ mRegistered = false;
+ // TODO: unregister buffers from hw
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+int Stream::getType()
+{
+ return mType;
+}
+
+bool Stream::isInputType()
+{
+ return mType & (CAMERA3_STREAM_INPUT | CAMERA3_STREAM_BIDIRECTIONAL);
+}
+
+bool Stream::isOutputType()
+{
+ return mType & (CAMERA3_STREAM_OUTPUT | CAMERA3_STREAM_BIDIRECTIONAL);
+}
+
+bool Stream::isValidReuseStream(int id, camera3_stream_t *s)
+{
+ if (id != mId) {
+ ALOGE("%s:%d: Invalid camera id for reuse. Got %d expect %d",
+ __func__, mId, id, mId);
+ return false;
+ }
+ if (s != mStream) {
+ ALOGE("%s:%d: Invalid stream handle for reuse. Got %p expect %p",
+ __func__, mId, s, mStream);
+ return false;
+ }
+ if (s->stream_type != mType) {
+ // TODO: prettyprint type string
+ ALOGE("%s:%d: Mismatched type in reused stream. Got %d expect %d",
+ __func__, mId, s->stream_type, mType);
+ return false;
+ }
+ if (s->format != mFormat) {
+ // TODO: prettyprint format string
+ ALOGE("%s:%d: Mismatched format in reused stream. Got %d expect %d",
+ __func__, mId, s->format, mFormat);
+ return false;
+ }
+ if (s->width != mWidth) {
+ ALOGE("%s:%d: Mismatched width in reused stream. Got %d expect %d",
+ __func__, mId, s->width, mWidth);
+ return false;
+ }
+ if (s->height != mHeight) {
+ ALOGE("%s:%d: Mismatched height in reused stream. Got %d expect %d",
+ __func__, mId, s->height, mHeight);
+ return false;
+ }
+ return true;
+}
+
+} // namespace default_camera_hal
diff --git a/modules/camera/Stream.h b/modules/camera/Stream.h
new file mode 100644
index 0000000..9720289
--- /dev/null
+++ b/modules/camera/Stream.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STREAM_H_
+#define STREAM_H_
+
+#include <hardware/camera3.h>
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+
+namespace default_camera_hal {
+// Stream represents a single input or output stream for a camera device.
+class Stream {
+ public:
+ Stream(int id, camera3_stream_t *s);
+ ~Stream();
+
+ // validate that astream's parameters match this stream's parameters
+ bool isValidReuseStream(int id, camera3_stream_t *s);
+
+ void setUsage(uint32_t usage);
+ void setMaxBuffers(uint32_t max_buffers);
+
+ int getType();
+ bool isInputType();
+ bool isOutputType();
+ bool getRegistered();
+
+ // This stream is being reused. Used in stream configuration passes
+ bool mReuse;
+
+ private:
+ // The camera device id this stream belongs to
+ const int mId;
+ // Handle to framework's stream, used as a cookie for buffers
+ const camera3_stream_t *mStream;
+ // Stream type: CAMERA3_STREAM_* (see <hardware/camera3.h>)
+ const int mType;
+ // Width in pixels of the buffers in this stream
+ const uint32_t mWidth;
+ // Height in pixels of the buffers in this stream
+ const uint32_t mHeight;
+ // Gralloc format: HAL_PIXEL_FORMAT_* (see <system/graphics.h>)
+ const int mFormat;
+ // Gralloc usage mask : GRALLOC_USAGE_* (see <hardware/gralloc.h>)
+ uint32_t mUsage;
+ // Max simultaneous in-flight buffers for this stream
+ uint32_t mMaxBuffers;
+ // Buffers have been registered for this stream and are ready
+ bool mRegistered;
+ // Lock protecting the Stream object for modifications
+ pthread_mutex_t mMutex;
+};
+} // namespace default_camera_hal
+
+#endif // STREAM_H_