summaryrefslogtreecommitdiff
path: root/src/gstreamer/gstlibcamera-utils.h
AgeCommit message (Expand)Author
2024-01-09gstreamer: Support for pre-1.16 GstEventLaurent Pinchart
2022-11-12gstreamer: Provide framerate support for libcamerasrcRishikesh Donadkar
2022-07-04gstreamer: Use gst_task_resume() when availableLaurent Pinchart
2021-11-24gstreamer: Convert to pragma onceKieran Bingham
2021-09-28gstreamer: Fix spelling of the work manager used in a util functionVedant Paranjape
2021-08-26gstreamer: Fix concurrent access issues to CameraManagerNicolas Dufresne
2020-03-07gst: utils: Factor-out the task resume helperJakub Adam
2020-03-07gst: utils: Add StreamConfiguration helpersNicolas Dufresne
2020-03-07gst: utils: Add simple scoped lockers for GMutex and GRectMutexNicolas Dufresne
2020-03-07gst: Add utility to convert StreamFormats to GstCapsNicolas Dufresne
d='n114' href='#n114'>114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2021, Google Inc.
 *
 * camera_hal_config.cpp - Camera HAL configuration file manager
 */
#include "camera_hal_config.h"

#include <filesystem>
#include <stdlib.h>
#include <string>

#include <libcamera/base/file.h>
#include <libcamera/base/log.h>

#include "libcamera/internal/yaml_parser.h"

#include <hardware/camera3.h>

using namespace libcamera;

LOG_DEFINE_CATEGORY(HALConfig)

class CameraHalConfig::Private : public Extensible::Private
{
	LIBCAMERA_DECLARE_PUBLIC(CameraHalConfig)

public:
	Private();

	int parseConfigFile(File &file, std::map<std::string, CameraConfigData> *cameras);

private:
	int parseCameraConfigData(const std::string &cameraId, const YamlObject &);
	int parseLocation(const YamlObject &, CameraConfigData &cameraConfigData);
	int parseRotation(const YamlObject &, CameraConfigData &cameraConfigData);

	std::map<std::string, CameraConfigData> *cameras_;
};

CameraHalConfig::Private::Private()
{
}

int CameraHalConfig::Private::parseConfigFile(File &file,
					      std::map<std::string, CameraConfigData> *cameras)
{
	/*
	 * Parse the HAL properties.
	 *
	 * Each camera properties block is a list of properties associated
	 * with the ID (as assembled by CameraSensor::generateId()) of the
	 * camera they refer to.
	 *
	 * cameras:
	 *   "camera0 id":
	 *     location: value
	 *     rotation: value
	 *     ...
	 *
	 *   "camera1 id":
	 *     location: value
	 *     rotation: value
	 *     ...
	 */

	cameras_ = cameras;

	std::unique_ptr<YamlObject> root = YamlParser::parse(file);
	if (!root)
		return -EINVAL;

	if (!root->isDictionary())
		return -EINVAL;

	/* Parse property "cameras" */
	if (!root->contains("cameras"))
		return -EINVAL;

	const YamlObject &yamlObjectCameras = (*root)["cameras"];

	if (!yamlObjectCameras.isDictionary())
		return -EINVAL;

	for (const auto &[cameraId, configData] : yamlObjectCameras.asDict()) {
		if (parseCameraConfigData(cameraId, configData))
			return -EINVAL;
	}

	return 0;
}

int CameraHalConfig::Private::parseCameraConfigData(const std::string &cameraId,
						    const YamlObject &cameraObject)

{
	if (!cameraObject.isDictionary())
		return -EINVAL;

	CameraConfigData &cameraConfigData = (*cameras_)[cameraId];

	/* Parse property "location" */
	if (parseLocation(cameraObject, cameraConfigData))
		return -EINVAL;

	/* Parse property "rotation" */
	if (parseRotation(cameraObject, cameraConfigData))
		return -EINVAL;

	return 0;
}

int CameraHalConfig::Private::parseLocation(const YamlObject &cameraObject,
					    CameraConfigData &cameraConfigData)
{
	if (!cameraObject.contains("location"))
		return -EINVAL;

	std::string location = cameraObject["location"].get<std::string>("");

	if (location == "front")
		cameraConfigData.facing = CAMERA_FACING_FRONT;
	else if (location == "back")
		cameraConfigData.facing = CAMERA_FACING_BACK;
	else
		return -EINVAL;

	return 0;
}

int CameraHalConfig::Private::parseRotation(const YamlObject &cameraObject,
					    CameraConfigData &cameraConfigData)
{
	if (!cameraObject.contains("rotation"))
		return -EINVAL;

	int32_t rotation = cameraObject["rotation"].get<int32_t>(-1);

	if (rotation < 0 || rotation >= 360) {
		LOG(HALConfig, Error)
			<< "Unknown rotation: " << rotation;
		return -EINVAL;
	}

	cameraConfigData.rotation = rotation;
	return 0;
}

CameraHalConfig::CameraHalConfig()
	: Extensible(std::make_unique<Private>()), exists_(false), valid_(false)
{
	parseConfigurationFile();
}

/*
 * Open the HAL configuration file and validate its content.
 * Return 0 on success, a negative error code otherwise
 * retval -ENOENT The configuration file is not available
 * retval -EINVAL The configuration file is available but not valid
 */
int CameraHalConfig::parseConfigurationFile()
{
	std::filesystem::path filePath = LIBCAMERA_SYSCONF_DIR;
	filePath /= "camera_hal.yaml";
	if (!std::filesystem::is_regular_file(filePath)) {
		LOG(HALConfig, Debug)
			<< "Configuration file: \"" << filePath << "\" not found";
		return -ENOENT;
	}

	File file(filePath);
	if (!file.open(File::OpenModeFlag::ReadOnly)) {
		int ret = file.error();
		LOG(HALConfig, Error) << "Failed to open configuration file "
				      << filePath << ": " << strerror(-ret);
		return ret;
	}

	exists_ = true;

	int ret = _d()->parseConfigFile(file, &cameras_);
	if (ret)
		return -EINVAL;

	valid_ = true;

	for (const auto &c : cameras_) {
		const std::string &cameraId = c.first;
		const CameraConfigData &camera = c.second;
		LOG(HALConfig, Debug) << "'" << cameraId << "' "
				      << "(" << camera.facing << ")["
				      << camera.rotation << "]";
	}

	return 0;
}

const CameraConfigData *CameraHalConfig::cameraConfigData(const std::string &cameraId) const
{
	const auto &it = cameras_.find(cameraId);
	if (it == cameras_.end()) {
		LOG(HALConfig, Error)
			<< "Camera '" << cameraId
			<< "' not described in the HAL configuration file";
		return nullptr;
	}

	return &it->second;
}