[libcamera-devel] [RFC PATCH 2/5] libcamera: V4L2Subdevice: Add getter/setter function for test pattern mode

Hirokazu Honda hiroh at chromium.org
Fri Apr 9 06:32:05 CEST 2021


The supported test pattern modes can be obtained by calling
VIDIOC_QUERYMENU to a camera sensor device. This implements the
getter and setter functions for the test pattern mode in
V4L2SubDevice.

Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
---
 include/libcamera/internal/v4l2_subdevice.h |   5 +
 src/libcamera/v4l2_subdevice.cpp            | 104 ++++++++++++++++++++
 2 files changed, 109 insertions(+)

diff --git a/include/libcamera/internal/v4l2_subdevice.h b/include/libcamera/internal/v4l2_subdevice.h
index d2b9ca55..f2f5d3f6 100644
--- a/include/libcamera/internal/v4l2_subdevice.h
+++ b/include/libcamera/internal/v4l2_subdevice.h
@@ -60,6 +60,9 @@ public:
 	int setFormat(unsigned int pad, V4L2SubdeviceFormat *format,
 		      Whence whence = ActiveFormat);
 
+	std::vector<int32_t> getAvailableTestPatternModes();
+	int setTestPatternMode(int32_t testPatternMode);
+
 	static std::unique_ptr<V4L2Subdevice>
 	fromEntityName(const MediaDevice *media, const std::string &entity);
 
@@ -74,6 +77,8 @@ private:
 					    unsigned int code);
 
 	const MediaEntity *entity_;
+
+	std::map<int32_t, uint32_t> testPatternModeMap_;
 };
 
 } /* namespace libcamera */
diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp
index 721ff5a9..130e9c4d 100644
--- a/src/libcamera/v4l2_subdevice.cpp
+++ b/src/libcamera/v4l2_subdevice.cpp
@@ -24,6 +24,7 @@
 #include "libcamera/internal/media_object.h"
 #include "libcamera/internal/utils.h"
 
+#include "android/metadata/system/camera_metadata_tags.h"
 /**
  * \file v4l2_subdevice.h
  * \brief V4L2 Subdevice API
@@ -523,4 +524,107 @@ std::vector<SizeRange> V4L2Subdevice::enumPadSizes(unsigned int pad,
 	return sizes;
 }
 
+/**
+ * \var V4L2Subdevice::testPatternModeMap_
+ * \brief The map from controls::SensorTestPatternMode to an index value to be
+ * used for V4L2_CID_TEST_PATTERN.
+ *
+ * The map is constructed in getAvailableTestPatternModes() and referred in
+ * setTestPatternMode() to find a value associated with the requested test
+ * pattern mode.
+ */
+/**
+ * \fn V4L2Subdevice::getAvailableTestPatternModes()
+ * \brief Retrieve the available test pattern modes.
+ *
+ * \return The available control::SensorTestPatternMode values.
+ */
+std::vector<int32_t> V4L2Subdevice::getAvailableTestPatternModes()
+{
+	std::vector<int32_t> patternModes;
+	if (!testPatternModeMap_.empty()) {
+		for (const auto &mode : testPatternModeMap_)
+			patternModes.push_back(mode.first);
+		return patternModes;
+	}
+
+	v4l2_queryctrl ctrl;
+	memset(&ctrl, 0, sizeof(ctrl));
+	ctrl.id = V4L2_CID_TEST_PATTERN;
+	int ret = ioctl(VIDIOC_QUERYCTRL, &ctrl);
+	if (ret < 0) {
+		LOG(V4L2, Error) << "Unable to get test pattern mode :"
+				 << strerror(-ret);
+		return {};
+	}
+
+	v4l2_querymenu menu;
+	memset(&menu, 0, sizeof(menu));
+	menu.id = ctrl.id;
+	for (menu.index = ctrl.minimum;
+	     static_cast<int>(menu.index) <= ctrl.maximum; menu.index++) {
+		if (ioctl(VIDIOC_QUERYMENU, &menu) != 0) {
+			continue;
+		}
+
+		const std::string modeName(reinterpret_cast<char *>(menu.name));
+		std::optional<int32_t> androidTestPatternMode;
+		/*
+		 * ov13858 and ov5670.
+		 * No corresponding value for "Vertical Color Bar Type 3" and
+		 * "Vertical Color Bar Type 4".
+		 */
+		if (modeName == "Disabled") {
+			androidTestPatternMode =
+				ANDROID_SENSOR_TEST_PATTERN_MODE_OFF;
+		} else if (modeName == "Vertical Color Bar Type 1") {
+			androidTestPatternMode =
+				ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS;
+		} else if (modeName == "Vertical Color Bar Type 2") {
+			androidTestPatternMode =
+				ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY;
+		}
+
+		if (androidTestPatternMode) {
+			testPatternModeMap_[*androidTestPatternMode] = menu.index;
+			patternModes.push_back(*androidTestPatternMode);
+		} else {
+			LOG(V4L2, Debug) << "Skip test pattern mode: "
+					 << modeName;
+		}
+	}
+
+	return patternModes;
+}
+
+/**
+ * \fn V4L2Subdevice::getAvailableTestPatternModes()
+ * \brief Set the test pattern mode.
+ *
+ * \return 0 on success or a negative error code otherwise.
+ */
+int V4L2Subdevice::setTestPatternMode(int32_t testPatternMode)
+{
+	auto it = testPatternModeMap_.find(testPatternMode);
+	if (it != testPatternModeMap_.end()) {
+		LOG(V4L2, Error) << "Unsupported test pattern mode: "
+				 << testPatternMode;
+
+		return -EINVAL;
+	}
+
+	v4l2_control ctrl;
+	memset(&ctrl, 0, sizeof(ctrl));
+	ctrl.id = V4L2_CID_TEST_PATTERN;
+	ctrl.value = it->second;
+	int ret = ioctl(VIDIOC_S_CTRL, &ctrl);
+	if (ret < 0) {
+		LOG(V4L2, Error) << "Unable to set test pattern mode: "
+				 << strerror(-ret);
+
+		return -EINVAL;
+	}
+
+	return 0;
+}
 } /* namespace libcamera */
-- 
2.31.1.295.g9ea45b61b8-goog



More information about the libcamera-devel mailing list