[libcamera-devel] [PATCH v6 07/15] pipeline: raspberrypi: Read config parameters from a file

Naushir Patuck naush at raspberrypi.com
Fri Jan 27 16:43:14 CET 2023


Add the ability to read the platform configuration parameters from a
config file provided by the user through the LIBCAMERA_RPI_CONFIG_FILE
environment variable. Use the PipelineHandler::configurationFile()
helper to determine the full path of the file.

Provide an example configuration file named example.yaml. Currently two
parameters are available through the json file:

"min_unicam_buffers" The minimum number of internal Unicam buffers to
allocate.

"min_total_unicam_buffers" The minimum number of internal + external
Unicam buffers that must be allocated.

Signed-off-by: Naushir Patuck <naush at raspberrypi.com>
Reviewed-by: David Plowman <david.plowman at raspberrypi.com>
---
 Documentation/environment_variables.rst       |  5 +++
 .../pipeline/raspberrypi/data/example.yaml    | 32 +++++++++++++
 .../pipeline/raspberrypi/data/meson.build     |  8 ++++
 .../pipeline/raspberrypi/meson.build          |  2 +
 .../pipeline/raspberrypi/raspberrypi.cpp      | 45 +++++++++++++++++++
 5 files changed, 92 insertions(+)
 create mode 100644 src/libcamera/pipeline/raspberrypi/data/example.yaml
 create mode 100644 src/libcamera/pipeline/raspberrypi/data/meson.build

diff --git a/Documentation/environment_variables.rst b/Documentation/environment_variables.rst
index f092cbbd29c5..ceeb251a2ac0 100644
--- a/Documentation/environment_variables.rst
+++ b/Documentation/environment_variables.rst
@@ -37,6 +37,11 @@ LIBCAMERA_IPA_MODULE_PATH
 
    Example value: ``${HOME}/.libcamera/lib:/opt/libcamera/vendor/lib``
 
+LIBCAMERA_RPI_CONFIG_FILE
+   Define a custom configuration file to use in the Raspberry Pi pipeline handler.
+
+   Example value: ``/usr/local/share/libcamera/pipeline/raspberrypi/minimal_mem.yaml``
+
 Further details
 ---------------
 
diff --git a/src/libcamera/pipeline/raspberrypi/data/example.yaml b/src/libcamera/pipeline/raspberrypi/data/example.yaml
new file mode 100644
index 000000000000..4662136e0be0
--- /dev/null
+++ b/src/libcamera/pipeline/raspberrypi/data/example.yaml
@@ -0,0 +1,32 @@
+{
+        "version": 1.0,
+        "target": "bcm2835",
+
+        "pipeline_handler":
+        {
+                # The minimum number of internal buffers to be allocated for
+                # Unicam. This value must be greater than 0, but less than or
+                # equal to min_total_unicam_buffers.
+                #
+                # A larger number of internal buffers can reduce the occurrence
+                # of frame drops during high CPU loads, but might also cause
+                # additional latency in the system.
+                #
+                # Note that the pipeline handler might override this value and
+                # not allocate any internal buffers if it knows they will never
+                # be used. For example if the RAW stream is marked as mandatory
+                # and there are no dropped frames signalled for algorithm
+                # convergence.
+                #
+                # "min_unicam_buffers": 2,
+
+                # The minimum total (internal + external) buffer count used for
+                # Unicam. The number of internal buffers allocated for Unicam is
+                # given by:
+                #
+                # internal buffer count = max(min_unicam_buffers,
+                #         min_total_unicam_buffers - external buffer count)
+                #
+                # "min_total_unicam_buffers": 4
+        }
+}
diff --git a/src/libcamera/pipeline/raspberrypi/data/meson.build b/src/libcamera/pipeline/raspberrypi/data/meson.build
new file mode 100644
index 000000000000..1c70433bbcbc
--- /dev/null
+++ b/src/libcamera/pipeline/raspberrypi/data/meson.build
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: CC0-1.0
+
+conf_files = files([
+    'example.yaml',
+])
+
+install_data(conf_files,
+             install_dir : pipeline_data_dir / 'raspberrypi')
diff --git a/src/libcamera/pipeline/raspberrypi/meson.build b/src/libcamera/pipeline/raspberrypi/meson.build
index 6064a3f00122..59e8fb18c555 100644
--- a/src/libcamera/pipeline/raspberrypi/meson.build
+++ b/src/libcamera/pipeline/raspberrypi/meson.build
@@ -6,3 +6,5 @@ libcamera_sources += files([
     'raspberrypi.cpp',
     'rpi_stream.cpp',
 ])
+
+subdir('data')
diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
index 44b1727678c7..83e82bd2880d 100644
--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
@@ -14,6 +14,7 @@
 #include <unordered_set>
 #include <utility>
 
+#include <libcamera/base/file.h>
 #include <libcamera/base/shared_fd.h>
 #include <libcamera/base/utils.h>
 
@@ -39,6 +40,7 @@
 #include "libcamera/internal/media_device.h"
 #include "libcamera/internal/pipeline_handler.h"
 #include "libcamera/internal/v4l2_videodevice.h"
+#include "libcamera/internal/yaml_parser.h"
 
 #include "delayed_controls.h"
 #include "dma_heaps.h"
@@ -1154,6 +1156,7 @@ int PipelineHandlerRPi::queueRequestDevice(Camera *camera, Request *request)
 			 */
 			stream->setExternalBuffer(buffer);
 		}
+
 		/*
 		 * If no buffer is provided by the request for this stream, we
 		 * queue a nullptr to the stream to signify that it must use an
@@ -1687,6 +1690,48 @@ int RPiCameraData::loadPipelineConfiguration()
 		.minTotalUnicamBuffers = 4,
 	};
 
+	char const *configFromEnv = utils::secure_getenv("LIBCAMERA_RPI_CONFIG_FILE");
+	if (!configFromEnv || *configFromEnv == '\0')
+		return 0;
+
+	std::string filename = std::string(configFromEnv);
+	File file(filename);
+
+	if (!file.open(File::OpenModeFlag::ReadOnly)) {
+		LOG(RPI, Error) << "Failed to open configuration file '" << filename << "'";
+		return -EIO;
+	}
+
+	LOG(RPI, Info) << "Using configuration file '" << filename << "'";
+
+	std::unique_ptr<YamlObject> root = YamlParser::parse(file);
+	if (!root) {
+		LOG(RPI, Warning) << "Failed to parse configuration file, using defaults";
+		return 0;
+	}
+
+	std::optional<double> ver = (*root)["version"].get<double>();
+	if (!ver || *ver != 1.0) {
+		LOG(RPI, Error) << "Unexpected configuration file version reported";
+		return -EINVAL;
+	}
+
+	const YamlObject &phConfig = (*root)["pipeline_handler"];
+	config_.minUnicamBuffers =
+		phConfig["min_unicam_buffers"].get<unsigned int>(config_.minUnicamBuffers);
+	config_.minTotalUnicamBuffers =
+		phConfig["min_total_unicam_buffers"].get<unsigned int>(config_.minTotalUnicamBuffers);
+
+	if (config_.minTotalUnicamBuffers < config_.minUnicamBuffers) {
+		LOG(RPI, Error) << "Invalid configuration: min_total_unicam_buffers must be >= min_unicam_buffers";
+		return -EINVAL;
+	}
+
+	if (config_.minTotalUnicamBuffers < 1) {
+		LOG(RPI, Error) << "Invalid configuration: min_total_unicam_buffers must be >= 1";
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
-- 
2.25.1



More information about the libcamera-devel mailing list