OSDN Git Service

Revise camera HAL 2, and add unit test skeleton.
authorEino-Ville Talvala <etalvala@google.com>
Thu, 22 Mar 2012 20:11:05 +0000 (13:11 -0700)
committerEino-Ville Talvala <etalvala@google.com>
Wed, 11 Apr 2012 18:23:31 +0000 (11:23 -0700)
- Add missing method in stream_ops (set_buffers_geometry)

- Remove extra method in stream_ops (set_swap_interval)

- Document metadata queue protocol

- Change metadata queue methods to be set/get through function calls
  only, instead of a struct member in the HAL device ops.

- Change vendor extension tag query methods to be retrieved by a get
  call, instead of a struct member in the HAL device ops.

- Add basic gtest unit test skeleton, which currently just returns
  static info from all camera devices.

Change-Id: I94117097b0243023ad60638070cc7f0cefec18e6

include/hardware/camera2.h
tests/camera2/Android.mk [new file with mode: 0644]
tests/camera2/camera2.cpp [new file with mode: 0644]

index 48f5c35..36f2a9e 100644 (file)
@@ -41,6 +41,8 @@
 
 __BEGIN_DECLS
 
+struct camera2_device;
+
 /**
  * Output image stream queue management
  */
@@ -53,6 +55,8 @@ typedef struct camera2_stream_ops {
     int (*cancel_buffer)(struct camera2_stream_ops* w,
                 buffer_handle_t* buffer);
     int (*set_buffer_count)(struct camera2_stream_ops* w, int count);
+    int (*set_buffers_geometry)(struct camera2_stream_ops* pw,
+                int w, int h, int format);
     int (*set_crop)(struct camera2_stream_ops *w,
                 int left, int top, int right, int bottom);
     // Timestamps are measured in nanoseconds, and must be comparable
@@ -62,7 +66,6 @@ typedef struct camera2_stream_ops {
     // The timestamp must be the time at the start of image exposure.
     int (*set_timestamp)(struct camera2_stream_ops *w, int64_t timestamp);
     int (*set_usage)(struct camera2_stream_ops* w, int usage);
-    int (*set_swap_interval)(struct camera2_stream_ops *w, int interval);
     int (*get_min_undequeued_buffer_count)(const struct camera2_stream_ops *w,
                 int *count);
     int (*lock_buffer)(struct camera2_stream_ops* w,
@@ -72,6 +75,32 @@ typedef struct camera2_stream_ops {
 /**
  * Metadata queue management, used for requests sent to HAL module, and for
  * frames produced by the HAL.
+ *
+ * Queue protocol:
+ *
+ * The source holds the queue and its contents. At start, the queue is empty.
+ *
+ * 1. When the first metadata buffer is placed into the queue, the source must
+ *    signal the destination by calling notify_queue_not_empty().
+ *
+ * 2. After receiving notify_queue_not_empty, the destination must call
+ *    dequeue() once it's ready to handle the next buffer.
+ *
+ * 3. Once the destination has processed a buffer, it should try to dequeue
+ *    another buffer. If there are no more buffers available, dequeue() will
+ *    return NULL. In this case, when a buffer becomes available, the source
+ *    must call notify_queue_not_empty() again. If the destination receives a
+ *    NULL return from dequeue, it does not need to query the queue again until
+ *    a notify_queue_not_empty() call is received from the source.
+ *
+ * 4. If the destination calls buffer_count() and receives 0, this does not mean
+ *    that the source will provide a notify_queue_not_empty() call. The source
+ *    must only provide such a call after the destination has received a NULL
+ *    from dequeue, or on initial startup.
+ *
+ * 5. The dequeue() call in response to notify_queue_not_empty() may be on the
+ *    same thread as the notify_queue_not_empty() call. The source must not
+ *    deadlock in that case.
  */
 
 typedef struct camera2_metadata_queue_src_ops {
@@ -99,6 +128,7 @@ typedef struct camera2_metadata_queue_dst_ops {
      * Notify destination that the queue is no longer empty
      */
     int (*notify_queue_not_empty)(struct camera2_metadata_queue_dst_ops *);
+
 } camera2_metadata_queue_dst_ops_t;
 
 /* Defined in camera_metadata.h */
@@ -153,32 +183,33 @@ enum {
     CAMERA2_MSG_ERROR_SERVER_FAULT =   0x0003
 };
 
-
-struct camera2_device;
 typedef struct camera2_device_ops {
     /**
      * Input request queue methods
      */
-    int (*set_request_queue_ops)(struct camera2_device *,
-            camera2_metadata_queue_src_ops *request_queue_src_ops);
+    int (*set_request_queue_src_ops)(struct camera2_device *,
+            camera2_metadata_queue_src_ops *queue_src_ops);
 
-    camera2_metadata_queue_dst_ops_t *request_queue_dst_ops;
+    int (*get_request_queue_dst_ops)(struct camera2_device *,
+            camera2_metadata_queue_dst_ops **queue_dst_ops);
 
     /**
      * Input reprocessing queue methods
      */
     int (*set_reprocess_queue_ops)(struct camera2_device *,
-            camera2_metadata_queue_src_ops *reprocess_queue_src_ops);
+            camera2_metadata_queue_src_ops *queue_src_ops);
 
-    camera2_metadata_queue_dst_ops_t *reprocess_queue_dst_ops;
+    int (*get_reprocess_queue_dst_ops)(struct camera2_device *,
+            camera2_metadata_queue_dst_ops **queue_dst_ops);
 
     /**
      * Output frame queue methods
      */
-    int (*set_frame_queue_ops)(struct camera2_device *,
-            camera2_metadata_queue_dst_ops *frame_queue_dst_ops);
+    int (*set_frame_queue_dst_ops)(struct camera2_device *,
+            camera2_metadata_queue_dst_ops *queue_dst_ops);
 
-    camera2_metadata_queue_src_ops_t *frame_queue_src_ops;
+    int (*get_frame_queue_src_ops)(struct camera2_device *,
+            camera2_metadata_queue_src_ops **queue_dst_ops);
 
     /**
      * Pass in notification methods
@@ -209,7 +240,8 @@ typedef struct camera2_device_ops {
     /**
      * Operations on the input reprocessing stream
      */
-    camera2_stream_ops_t *reprocess_stream_ops;
+    int (*get_reprocess_stream_ops)(struct camera2_device *,
+            camera2_stream_ops_t **stream_ops);
 
     /**
      * Get the number of streams that can be simultaneously allocated.
@@ -231,7 +263,7 @@ typedef struct camera2_device_ops {
         uint32_t stream_slot,
         uint32_t width,
         uint32_t height,
-        int format,
+        uint32_t format,
         camera2_stream_ops_t *camera2_stream_ops);
 
     /**
@@ -244,6 +276,13 @@ typedef struct camera2_device_ops {
         uint32_t stream_slot);
 
     /**
+     * Get methods to query for vendor extension metadata tag infomation. May
+     * set ops to NULL if no vendor extension tags are defined.
+     */
+    int (*get_metadata_vendor_tag_ops)(struct camera2_device*,
+            vendor_tag_query_ops_t **ops);
+
+    /**
      * Release the camera hardware.  Requests that are in flight will be
      * canceled. No further buffers will be pushed into any allocated pipelines
      * once this call returns.
@@ -251,12 +290,6 @@ typedef struct camera2_device_ops {
     void (*release)(struct camera2_device *);
 
     /**
-     * Methods to query for vendor extension metadata tag infomation. May be NULL
-     * if no vendor extension tags are defined.
-     */
-    vendor_tag_query_ops *camera_metadata_vendor_tag_ops;
-
-    /**
      * Dump state of the camera hardware
      */
     int (*dump)(struct camera2_device *, int fd);
diff --git a/tests/camera2/Android.mk b/tests/camera2/Android.mk
new file mode 100644 (file)
index 0000000..340ec30
--- /dev/null
@@ -0,0 +1,27 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+       camera2.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+       libutils \
+       libstlport \
+       libhardware \
+       libcamera_metadata
+
+LOCAL_STATIC_LIBRARIES := \
+       libgtest \
+       libgtest_main
+
+LOCAL_C_INCLUDES += \
+       bionic \
+       bionic/libstdc++/include \
+       external/gtest/include \
+       external/stlport/stlport \
+       system/media/camera/include \
+
+LOCAL_MODULE:= camera2_hal_tests
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/tests/camera2/camera2.cpp b/tests/camera2/camera2.cpp
new file mode 100644 (file)
index 0000000..d13d7cd
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2012 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 <system/camera_metadata.h>
+#include <hardware/camera2.h>
+#include <gtest/gtest.h>
+#include <iostream>
+
+class Camera2Test: public testing::Test {
+  public:
+    static void SetUpTestCase() {
+        int res;
+
+        hw_module_t *module = NULL;
+        res = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
+                (const hw_module_t **)&module);
+
+        ASSERT_EQ(0, res)
+                << "Failure opening camera hardware module: " << res;
+        ASSERT_TRUE(NULL != module)
+                << "No camera module was set by hw_get_module";
+
+        std::cout << "  Camera module name: " << module->name << std::endl;
+        std::cout << "  Camera module author: " << module->author << std::endl;
+        std::cout << "  Camera module API version: 0x" << std::hex
+                  << module->module_api_version << std::endl;
+        std::cout << "  Camera module HAL API version: 0x" << std::hex
+                  << module->hal_api_version << std::endl;
+
+        int16_t version2_0 = CAMERA_MODULE_API_VERSION_2_0;
+        ASSERT_EQ(version2_0, module->module_api_version)
+                << "Camera module version is 0x"
+                << std::hex << module->module_api_version
+                << ", not 2.0. (0x"
+                << std::hex << CAMERA_MODULE_API_VERSION_2_0 << ")";
+
+        sCameraModule = reinterpret_cast<camera_module_t*>(module);
+
+        sNumCameras = sCameraModule->get_number_of_cameras();
+        ASSERT_LT(0, sNumCameras) << "No camera devices available!";
+
+        std::cout << "  Camera device count: " << sNumCameras << std::endl;
+        sCameraSupportsHal2 = new bool[sNumCameras];
+
+        for (int i = 0; i < sNumCameras; i++) {
+            camera_info info;
+            res = sCameraModule->get_camera_info(i, &info);
+            ASSERT_EQ(0, res)
+                    << "Failure getting camera info for camera " << i;
+            std::cout << "  Camera device: " << std::dec
+                      << i << std::endl;;
+            std::cout << "    Facing: " << std::dec
+                      << info.facing  << std::endl;
+            std::cout << "    Orientation: " << std::dec
+                      << info.orientation  << std::endl;
+            std::cout << "    Version: 0x" << std::hex <<
+                    info.device_version  << std::endl;
+            if (info.device_version >= CAMERA_DEVICE_API_VERSION_2_0) {
+                sCameraSupportsHal2[i] = true;
+                ASSERT_TRUE(NULL != info.static_camera_characteristics);
+                std::cout << "    Static camera metadata:"  << std::endl;
+                dump_camera_metadata(info.static_camera_characteristics, 0, 1);
+            } else {
+                sCameraSupportsHal2[i] = false;
+            }
+        }
+    }
+
+    static const camera_module_t *getCameraModule() {
+        return sCameraModule;
+    }
+
+    static const camera2_device_t *openCameraDevice(int id) {
+        if (NULL == sCameraSupportsHal2) return NULL;
+        if (id >= sNumCameras) return NULL;
+        if (!sCameraSupportsHal2[id]) return NULL;
+
+        hw_device_t *device = NULL;
+        const camera_module_t *cam_module = getCameraModule();
+        char camId[10];
+        int res;
+
+        snprintf(camId, 10, "%d", id);
+        res = cam_module->common.methods->open(
+            (const hw_module_t*)cam_module,
+            camId,
+            &device);
+        if (res < 0 || cam_module == NULL) {
+            return NULL;
+        }
+        camera2_device_t *cam_device =
+                reinterpret_cast<camera2_device_t*>(device);
+        return cam_device;
+    }
+
+  private:
+
+    static camera_module_t *sCameraModule;
+    static int sNumCameras;
+    static bool *sCameraSupportsHal2;
+};
+
+camera_module_t *Camera2Test::sCameraModule = NULL;
+int Camera2Test::sNumCameras = 0;
+bool *Camera2Test::sCameraSupportsHal2 = NULL;
+
+
+TEST_F(Camera2Test, Basic) {
+    ASSERT_TRUE(NULL != getCameraModule());
+}