summaryrefslogtreecommitdiff
path: root/Documentation/theme/static/css/theme.css
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/theme/static/css/theme.css')
0 files changed, 0 insertions, 0 deletions
' href='#n60'>60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 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 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * camera_sensor.cpp - A camera sensor
 */

#include "camera_sensor.h"

#include <algorithm>
#include <float.h>
#include <iomanip>
#include <limits.h>
#include <math.h>

#include "formats.h"
#include "v4l2_subdevice.h"

/**
 * \file camera_sensor.h
 * \brief A camera sensor
 */

namespace libcamera {

LOG_DEFINE_CATEGORY(CameraSensor);

/**
 * \class CameraSensor
 * \brief A camera sensor based on V4L2 subdevices
 *
 * The CameraSensor class eases handling of sensors for pipeline handlers by
 * hiding the details of the V4L2 subdevice kernel API and caching sensor
 * information.
 *
 * The implementation is currently limited to sensors that expose a single V4L2
 * subdevice with a single pad, and support the same frame sizes for all
 * supported media bus codes. It will be extended to support more complex
 * devices as the needs arise.
 */

/**
 * \brief Construct a CameraSensor
 * \param[in] entity The media entity backing the camera sensor
 *
 * Once constructed the instance must be initialized with init().
 */
CameraSensor::CameraSensor(const MediaEntity *entity)
	: entity_(entity)
{
	subdev_ = new V4L2Subdevice(entity);
}

/**
 * \brief Destroy a CameraSensor
 */
CameraSensor::~CameraSensor()
{
	delete subdev_;
}

/**
 * \brief Initialize the camera sensor instance
 *
 * This method performs the initialisation steps of the CameraSensor that may
 * fail. It shall be called once and only once after constructing the instance.
 *
 * \return 0 on success or a negative error code otherwise
 */
int CameraSensor::init()
{
	int ret;

	if (entity_->pads().size() != 1) {
		LOG(CameraSensor, Error)
			<< "Sensors with more than one pad are not supported";
		return -EINVAL;
	}

	if (entity_->function() != MEDIA_ENT_F_CAM_SENSOR) {
		LOG(CameraSensor, Error)
			<< "Invalid sensor function 0x"
			<< std::hex << std::setfill('0') << std::setw(8)
			<< entity_->function();
		return -EINVAL;
	}

	ret = subdev_->open();
	if (ret < 0)
		return ret;

	/* Enumerate and cache media bus codes and sizes. */
	const FormatEnum formats = subdev_->formats(0);
	if (formats.empty()) {
		LOG(CameraSensor, Error) << "No image format found";
		return -EINVAL;
	}

	std::transform(formats.begin(), formats.end(),
		       std::back_inserter(mbusCodes_),
		       [](decltype(*formats.begin()) f) { return f.first; });

	/*
	 * Extract the supported sizes from the first format as we only support
	 * sensors that offer the same frame sizes for all media bus codes.
	 * Verify this assumption and reject the sensor if it isn't true.
	 */
	const std::vector<SizeRange> &sizes = formats.begin()->second;
	std::transform(sizes.begin(), sizes.end(), std::back_inserter(sizes_),
		       [](const SizeRange &range) { return range.max; });

	for (auto it = ++formats.begin(); it != formats.end(); ++it) {
		if (it->second != sizes) {
			LOG(CameraSensor, Error)
				<< "Frame sizes differ between media bus codes";
			return -EINVAL;
		}
	}

	/* Sort the media bus codes and sizes. */
	std::sort(mbusCodes_.begin(), mbusCodes_.end());
	std::sort(sizes_.begin(), sizes_.end());

	return 0;
}

/**
 * \fn CameraSensor::entity()
 * \brief Retrieve the sensor media entity
 * \return The sensor media entity
 */

/**
 * \fn CameraSensor::mbusCodes()
 * \brief Retrieve the media bus codes supported by the camera sensor
 * \return The supported media bus codes sorted in increasing order
 */

/**
 * \fn CameraSensor::sizes()
 * \brief Retrieve the frame sizes supported by the camera sensor
 * \return The supported frame sizes sorted in increasing order
 */

/**
 * \brief Retrieve the camera sensor resolution
 * \return The camera sensor resolution in pixels
 */
const Size &CameraSensor::resolution() const
{
	/*
	 * The sizes_ vector is sorted in ascending order, the resolution is
	 * thus the last element of the vector.
	 */
	return sizes_.back();
}

/**
 * \brief Retrieve the best sensor format for a desired output
 * \param[in] mbusCodes The list of acceptable media bus codes
 * \param[in] size The desired size
 *
 * Media bus codes are selected from \a mbusCodes, which lists all acceptable
 * codes in decreasing order of preference. This method selects the first code
 * from the list that is supported by the sensor. If none of the desired codes
 * is supported, it returns an error.
 *
 * \a size indicates the desired size at the output of the sensor. This method
 * selects the best size supported by the sensor according to the following
 * criteria.
 *
 * - The desired \a size shall fit in the sensor output size to avoid the need
 *   to up-scale.
 * - The sensor output size shall match the desired aspect ratio to avoid the
 *   need to crop the field of view.
 * - The sensor output size shall be as small as possible to lower the required
 *   bandwidth.
 *
 * The use of this method is optional, as the above criteria may not match the
 * needs of all pipeline handlers. Pipeline handlers may implement custom
 * sensor format selection when needed.
 *
 * The returned sensor output format is guaranteed to be acceptable by the
 * setFormat() method without any modification.
 *
 * \return The best sensor output format matching the desired media bus codes
 * and size on success, or an empty format otherwise.
 */
V4L2SubdeviceFormat CameraSensor::getFormat(const std::vector<unsigned int> &mbusCodes,
					    const Size &size) const
{
	V4L2SubdeviceFormat format{};

	for (unsigned int code : mbusCodes_) {
		if (std::any_of(mbusCodes.begin(), mbusCodes.end(),
				[code](unsigned int c) { return c == code; })) {
			format.mbus_code = code;
			break;
		}
	}