summaryrefslogtreecommitdiff
path: root/test/libtest/buffer_source.cpp
blob: ee87c8cd821c373ff16f494a5e89a3af956a80aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2020, Google Inc.
 *
 * A provider of external buffers, suitable for use in tests.
 */

#include "buffer_source.h"

#include <iostream>
#include <memory>

#include "libcamera/internal/device_enumerator.h"

#include "test.h"

BufferSource::BufferSource()
{
}

BufferSource::~BufferSource()
{
	if (media_)
		media_->release();
}

int BufferSource::allocate(const StreamConfiguration &config)
{
	/* Locate and open the video device. */
	std::string videoDeviceName = "vivid-000-vid-out";

	std::unique_ptr<DeviceEnumerator> enumerator =
		DeviceEnumerator::create();
	if (!enumerator) {
		std::cout << "Failed to create device enumerator" << std::endl;
		return TestFail;
	}

	if (enumerator->enumerate()) {
		std::cout << "Failed to enumerate media devices" << std::endl;
		return TestFail;
	}

	DeviceMatch dm("vivid");
	dm.add(videoDeviceName);

	media_ = enumerator->search(dm);
	if (!media_) {
		std::cout << "No vivid output device available" << std::endl;
		return TestSkip;
	}

	std::unique_ptr<V4L2VideoDevice> video{ V4L2VideoDevice::fromEntityName(media_.get(), videoDeviceName) };
	if (!video) {
		std::cout << "Failed to get video device from entity "
			  << videoDeviceName << std::endl;
		return TestFail;
	}

	if (video->open()) {
		std::cout << "Unable to open " << videoDeviceName << std::endl;
		return TestFail;
	}

	/* Configure the format. */
	V4L2DeviceFormat format;
	if (video->getFormat(&format)) {
		std::cout << "Failed to get format on output device" << std::endl;
		return TestFail;
	}

	format.size = config.size;
	format.fourcc = V4L2PixelFormat::fromPixelFormat(config.pixelFormat,
							 false);
	if (video->setFormat(&format)) {
		std::cout << "Failed to set format on output device" << std::endl;
		return TestFail;
	}

	if (video->allocateBuffers(config.bufferCount, &buffers_) < 0) {
		std::cout << "Failed to allocate buffers" << std::endl;
		return TestFail;
	}

	video->close();

	return TestPass;
}

const std::vector<std::unique_ptr<FrameBuffer>> &BufferSource::buffers()
{
	return buffers_;
}
class="hl opt">= 64, .pipelineWidth = 16, .statsInline = true, /* * The constraint below is on the rate of pixels going * from CSI2 peripheral to ISP-FE (400Mpix/s, plus tiny * overheads per scanline, for which 380Mpix/s is a * conservative bound). * * There is a 64kbit data FIFO before the bottleneck, * which means that in all reasonable cases the * constraint applies at a timescale >= 1 scanline, so * adding horizontal blanking can prevent loss. * * If the backlog were to grow beyond 64kbit during a * single scanline, there could still be loss. This * could happen using 4 lanes at 1.5Gbps at 10bpp with * frames wider than ~16,000 pixels. */ .minPixelProcessingTime = 1.0us / 380, } }, }; Controller::Controller() : switchModeCalled_(false) { } Controller::~Controller() {} int Controller::read(char const *filename) { File file(filename); if (!file.open(File::OpenModeFlag::ReadOnly)) { LOG(RPiController, Warning) << "Failed to open tuning file '" << filename << "'"; return -EINVAL; } std::unique_ptr<YamlObject> root = YamlParser::parse(file); if (!root) return -EINVAL; double version = (*root)["version"].get<double>(1.0); target_ = (*root)["target"].get<std::string>("bcm2835"); if (version < 2.0) { LOG(RPiController, Warning) << "This format of the tuning file will be deprecated soon!" << " Please use the convert_tuning.py utility to update to version 2.0."; for (auto const &[key, value] : root->asDict()) { int ret = createAlgorithm(key, value); if (ret) return ret; } } else if (version < 3.0) { if (!root->contains("algorithms")) { LOG(RPiController, Error) << "Tuning file " << filename << " does not have an \"algorithms\" list!"; return -EINVAL; } for (auto const &rootAlgo : (*root)["algorithms"].asList()) for (auto const &[key, value] : rootAlgo.asDict()) { int ret = createAlgorithm(key, value); if (ret) return ret; } } else { LOG(RPiController, Error) << "Unrecognised version " << version << " for the tuning file " << filename; return -EINVAL; } return 0; } int Controller::createAlgorithm(const std::string &name, const YamlObject &params) { auto it = getAlgorithms().find(name); if (it == getAlgorithms().end()) { LOG(RPiController, Warning) << "No algorithm found for \"" << name << "\""; return 0; } Algorithm *algo = (*it->second)(this); int ret = algo->read(params); if (ret) return ret; algorithms_.push_back(AlgorithmPtr(algo)); return 0; } void Controller::initialise() { for (auto &algo : algorithms_) algo->initialise(); } void Controller::switchMode(CameraMode const &cameraMode, Metadata *metadata) { for (auto &algo : algorithms_) algo->switchMode(cameraMode, metadata); switchModeCalled_ = true; } void Controller::prepare(Metadata *imageMetadata) { assert(switchModeCalled_); for (auto &algo : algorithms_) algo->prepare(imageMetadata); } void Controller::process(StatisticsPtr stats, Metadata *imageMetadata) { assert(switchModeCalled_); for (auto &algo : algorithms_) algo->process(stats, imageMetadata); } Metadata &Controller::getGlobalMetadata() { return globalMetadata_; } Algorithm *Controller::getAlgorithm(std::string const &name) const { /* * The passed name must be the entire algorithm name, or must match the * last part of it with a period (.) just before. */ size_t nameLen = name.length(); for (auto &algo : algorithms_) { char const *algoName = algo->name(); size_t algoNameLen = strlen(algoName); if (algoNameLen >= nameLen && strcasecmp(name.c_str(), algoName + algoNameLen - nameLen) == 0 && (nameLen == algoNameLen || algoName[algoNameLen - nameLen - 1] == '.')) return algo.get(); } return nullptr; } const std::string &Controller::getTarget() const { return target_; } const Controller::HardwareConfig &Controller::getHardwareConfig() const { auto cfg = HardwareConfigMap.find(getTarget()); /* * This really should not happen, the IPA ought to validate the target * on initialisation. */ ASSERT(cfg != HardwareConfigMap.end()); return cfg->second; }