summaryrefslogtreecommitdiff
path: root/test/hotplug-cameras.cpp
AgeCommit message (Collapse)Author
2022-03-25libcamera: base: timer: Drop start() overload with int argumentLaurent Pinchart
The start(unsigned int msec) overload is error-prone, as the argument unit can easily be mistaken in callers. Drop it and update all callers to use the start(std::chrono::milliseconds) overload instead. The callers now need to use std::chrono_literals. The using statement could be added to timer.h for convenience, but "using" is discouraged in header files to avoid namespace pollution. Update the callers instead, and while at it, sort the "using" statements alphabetically in tests. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
2021-06-25libcamera/base: Move File to base libraryKieran Bingham
The File abstraction is a base helper and not part of the libcamera API. Move it to to allow usage by users of the base library. Reviewed-by: Hirokazu Honda <hiroh@chromium.org> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-06-25libcamera/base: Move extended base functionalityKieran Bingham
Move the functionality for the following components to the new base support library: - BoundMethod - EventDispatcher - EventDispatcherPoll - Log - Message - Object - Signal - Semaphore - Thread - Timer While it would be preferable to see these split to move one component per commit, these components are all interdependent upon each other, which leaves us with one big change performing the move for all of them. Reviewed-by: Hirokazu Honda <hiroh@chromium.org> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-11-15libcamera: Move EventDispatcher to internal APILaurent Pinchart
There's no user of the EventDispatcher (and the related EventNotifier and Timer classes) outside of libcamera. Move those classes to the internal API. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-08-25meson: Remove -Wno-unused-parameterLaurent Pinchart
We build libcamera with -Wno-unused-parameter and this doesn't cause much issue internally. However, it prevents catching unused parameters in inline functions defined in public headers. This can lead to compilation warnings for applications compiled without -Wno-unused-parameter. To catch those issues, remove -Wno-unused-parameter and fix all the related warnings with [[maybe_unused]]. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-06-17tests: Introduce hotplug hot-unplug unit testUmang Jain
This test checks the code-paths for camera's hotplugged and unplugged support. It is based on bind/unbind of a UVC device from sysfs. Hence, this test requires root permissions to run and should have at least one already bound UVC device present in the system. Signed-off-by: Umang Jain <email@uajain.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
59 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
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (C) 2019, Raspberry Pi (Trading) Limited
 *
 * cam_helper.cpp - helper information for different sensors
 */

#include <linux/videodev2.h>

#include <assert.h>
#include <map>
#include <string.h>

#include "libcamera/internal/v4l2_videodevice.h"

#include "cam_helper.hpp"
#include "md_parser.hpp"

using namespace RPiController;
using namespace libcamera;

namespace libcamera {
LOG_DECLARE_CATEGORY(IPARPI)
}

static std::map<std::string, CamHelperCreateFunc> cam_helpers;

CamHelper *CamHelper::Create(std::string const &cam_name)
{
	/*
	 * CamHelpers get registered by static RegisterCamHelper
	 * initialisers.
	 */
	for (auto &p : cam_helpers) {
		if (cam_name.find(p.first) != std::string::npos)
			return p.second();
	}

	return nullptr;
}

CamHelper::CamHelper(MdParser *parser, unsigned int frameIntegrationDiff)
	: parser_(parser), initialized_(false),
	  frameIntegrationDiff_(frameIntegrationDiff)
{
}

CamHelper::~CamHelper()
{
	delete parser_;
}

void CamHelper::Prepare(Span<const uint8_t> buffer,
			Metadata &metadata)
{
	parseEmbeddedData(buffer, metadata);
}

void CamHelper::Process([[maybe_unused]] StatisticsPtr &stats,
			[[maybe_unused]] Metadata &metadata)
{
}

uint32_t CamHelper::ExposureLines(double exposure_us) const
{
	assert(initialized_);
	return exposure_us * 1000.0 / mode_.line_length;
}

double CamHelper::Exposure(uint32_t exposure_lines) const
{
	assert(initialized_);
	return exposure_lines * mode_.line_length / 1000.0;
}

uint32_t CamHelper::GetVBlanking(double &exposure, double minFrameDuration,
				 double maxFrameDuration) const
{
	uint32_t frameLengthMin, frameLengthMax, vblank;
	uint32_t exposureLines = ExposureLines(exposure);

	assert(initialized_);

	/*
	 * minFrameDuration and maxFrameDuration are clamped by the caller
	 * based on the limits for the active sensor mode.
	 */
	frameLengthMin = 1e3 * minFrameDuration / mode_.line_length;
	frameLengthMax = 1e3 * maxFrameDuration / mode_.line_length;

	/*
	 * Limit the exposure to the maximum frame duration requested, and
	 * re-calculate if it has been clipped.
	 */
	exposureLines = std::min(frameLengthMax - frameIntegrationDiff_, exposureLines);
	exposure = Exposure(exposureLines);

	/* Limit the vblank to the range allowed by the frame length limits. */
	vblank = std::clamp(exposureLines + frameIntegrationDiff_,
			    frameLengthMin, frameLengthMax) - mode_.height;
	return vblank;
}

void CamHelper::SetCameraMode(const CameraMode &mode)
{
	mode_ = mode;
	if (parser_) {
		parser_->SetBitsPerPixel(mode.bitdepth);
		parser_->SetLineLengthBytes(0); /* We use SetBufferSize. */
	}
	initialized_ = true;
}

void CamHelper::GetDelays(int &exposure_delay, int &gain_delay,
			  int &vblank_delay) const
{
	/*
	 * These values are correct for many sensors. Other sensors will
	 * need to over-ride this method.
	 */
	exposure_delay = 2;
	gain_delay = 1;
	vblank_delay = 2;
}

bool CamHelper::SensorEmbeddedDataPresent() const
{
	return false;
}

unsigned int CamHelper::HideFramesStartup() const
{
	/*
	 * The number of frames when a camera first starts that shouldn't be
	 * displayed as they are invalid in some way.
	 */
	return 0;
}

unsigned int CamHelper::HideFramesModeSwitch() const
{
	/* After a mode switch, many sensors return valid frames immediately. */
	return 0;
}

unsigned int CamHelper::MistrustFramesStartup() const
{
	/* Many sensors return a single bad frame on start-up. */
	return 1;
}

unsigned int CamHelper::MistrustFramesModeSwitch() const
{
	/* Many sensors return valid metadata immediately. */
	return 0;
}

void CamHelper::parseEmbeddedData(Span<const uint8_t> buffer,
				  Metadata &metadata)
{
	if (buffer.empty())
		return;

	uint32_t exposureLines, gainCode;

	if (parser_->Parse(buffer) != MdParser::Status::OK ||
	    parser_->GetExposureLines(exposureLines) != MdParser::Status::OK ||
	    parser_->GetGainCode(gainCode) != MdParser::Status::OK) {
		LOG(IPARPI, Error) << "Embedded data buffer parsing failed";
		return;
	}

	/*
	 * Overwrite the exposure/gain values in the DeviceStatus, as
	 * we know better. Fetch it first in case any other fields were
	 * set meaningfully.
	 */
	DeviceStatus deviceStatus;

	if (metadata.Get("device.status", deviceStatus) != 0) {
		LOG(IPARPI, Error) << "DeviceStatus not found";
		return;
	}

	deviceStatus.shutter_speed = Exposure(exposureLines);
	deviceStatus.analogue_gain = Gain(gainCode);

	LOG(IPARPI, Debug) << "Metadata updated - Exposure : "
			   << deviceStatus.shutter_speed
			   << " Gain : "
			   << deviceStatus.analogue_gain;

	metadata.Set("device.status", deviceStatus);
}

RegisterCamHelper::RegisterCamHelper(char const *cam_name,
				     CamHelperCreateFunc create_func)
{
	cam_helpers[std::string(cam_name)] = create_func;
}