libcamera/src/android/camera_hal_config.cpp
Laurent Pinchart 12bf404147 android: Use the YamlObject iterator API
Replace usage of YamlObject::memberNames() with the more efficient
iterator API.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Han-Lin Chen <hanlinchen@chromium.org>
2022-06-20 15:12:12 +03:00

209 lines
4.9 KiB
C++

/* 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;
}