OSDN Git Service

modules: camera: Add Streams
authorAlex Ray <aray@google.com>
Fri, 1 Mar 2013 00:04:35 +0000 (16:04 -0800)
committerAlex Ray <aray@google.com>
Fri, 3 May 2013 19:16:18 +0000 (12:16 -0700)
Adds a Stream object, and configureStreams support in parsing the
provided stream_array. Streams are naively setup for sync-less software
painting.

Change-Id: Ibbd90e3e2c7fa984dd5d2dcbd4da7bf4dad43aa1

modules/camera/Android.mk
modules/camera/Camera.cpp
modules/camera/Camera.h
modules/camera/Stream.cpp [new file with mode: 0644]
modules/camera/Stream.h [new file with mode: 0644]

index eebffc1..823fe17 100644 (file)
@@ -26,6 +26,7 @@ LOCAL_C_INCLUDES += \
 LOCAL_SRC_FILES := \
        CameraHAL.cpp \
        Camera.cpp \
+       Stream.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
        libcamera_metadata \
index d477ef6..b06f65d 100644 (file)
@@ -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)
index f2ad093..c43e207 100644 (file)
@@ -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 (file)
index 0000000..08ae159
--- /dev/null
@@ -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 (file)
index 0000000..9720289
--- /dev/null
@@ -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_