/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019, Google Inc. * * ipa_proxy.cpp - Image Processing Algorithm proxy */ #include "ipa_proxy.h" #include #include #include "log.h" #include "utils.h" #include /** * \file ipa_proxy.h * \brief IPA Proxy */ namespace libcamera { LOG_DEFINE_CATEGORY(IPAProxy) /** * \class IPAProxy * \brief IPA Proxy * * Isolate IPA into separate process. * * Every subclass of proxy shall be registered with libcamera using * the REGISTER_IPA_PROXY() macro. */ /** * \brief Construct an IPAProxy instance * * IPAProxy instances shall be constructed through the IPAProxyFactory::create() * method implemented by the respective factories. */ IPAProxy::IPAProxy() : valid_(false) { } IPAProxy::~IPAProxy() { } /** * \fn IPAProxy::isValid() * \brief Check if the IPAProxy instance is valid * * An IPAProxy instance is valid if the IPA interface is successfully created in * isolation, and IPC is successfully set up. * * \return True if the IPAProxy is valid, false otherwise */ /** * \brief Find a valid full path for a proxy worker for a given executable name * \param[in] file File name of proxy worker executable * * A proxy worker's executable could be found in either the global installation * directory, or in the paths specified by the environment variable * LIBCAMERA_IPA_PROXY_PATH. This method checks the global install directory * first, then LIBCAMERA_IPA_PROXY_PATH in order, and returns the full path to * the proxy worker executable that is specified by file. The proxy worker * executable shall have exec permission. * * \return The full path to the proxy worker executable, or an empty string if * no valid executable path */ std::string IPAProxy::resolvePath(const std::string &file) const { /* Try finding the exec target from the install directory first */ std::string proxyFile = "/" + file; std::string proxyPath = std::string(IPA_PROXY_DIR) + proxyFile; if (!access(proxyPath.c_str(), X_OK)) return proxyPath; /* No exec target in install directory; check env variable. */ const char *execPaths = utils::secure_getenv("LIBCAMERA_IPA_PROXY_PATH"); while (execPaths) { const char *delim = strchrnul(execPaths, ':'); size_t count = delim - execPaths; if (count) { std::string proxyPath(execPaths, count); proxyPath += proxyFile; if (!access(proxyPath.c_str(), X_OK)) return proxyPath; } if (*delim == '\0') break; execPaths += count + 1; } return std::string(); } /** * \var IPAProxy::valid_ * \brief Flag to indicate if the IPAProxy instance is valid * * A IPAProxy instance is valid if the IPA interface is successfully created in * isolation, and IPC is successfully set up. * * This flag can be read via IPAProxy::isValid(). * * Implementations of the IPAProxy class should set this flag upon successful * construction. */ /** * \class IPAProxyFactory * \brief Registration of IPAProxy classes and creation of instances * * To facilitate discovery and instantiation of IPAProxy classes, the * IPAProxyFactory class maintains a registry of IPAProxy classes. Each * IPAProxy subclass shall register itself using the REGISTER_IPA_PROXY() * macro, which will create a corresponding instance of a IPAProxyFactory * subclass and register it with the static list of factories. */ /** * \brief Construct a IPAProxy factory * \param[in] name Name of the IPAProxy class * * Creating an instance of the factory registers is with the global list of * factories, accessible through the factories() function. * * The factory \a name is used for debugging and IPAProxy matching purposes * and shall be unique. */ IPAProxyFactory::IPAProxyFactory(const char *name) : name_(name) { registerType(this); } /** * \fn IPAProxyFactory::create() * \brief Create an instance of the IPAProxy corresponding to the factory * \param[in] ipam The IPA module * * This virtual function is implemented by the REGISTER_IPA_PROXY() macro. * It creates a IPAProxy instance that isolates an IPA interface designated * by the IPA module \a ipam. * * \return A pointer to a newly constructed instance of the IPAProxy subclass * corresponding to the factory */ /** * \fn IPAProxyFactory::name() * \brief Retrieve the factory name * \return The factory name */ /** * \brief Add a IPAProxy class to the registry * \param[in] factory Factory to use to construct the IPAProxy * * The caller is responsible to guarantee the uniqueness of the IPAProxy name. */ void IPAProxyFactory::registerType(IPAProxyFactory *factory) { std::vector &factories = IPAProxyFactory::factories(); factories.push_back(factory); LOG(IPAProxy, Debug) << "Registered proxy \"" << factory->name() << "\""; } /** * \brief Retrieve the list of all IPAProxy factories * * The static factories map is defined inside the function to ensure it gets * initialized on first use, without any dependency on link order. * * \return The list of pipeline handler factories */ std::vector &IPAProxyFactory::factories() { static std::vector factories; return factories; } /** * \def REGISTER_IPA_PROXY * \brief Register a IPAProxy with the IPAProxy factory * \param[in] proxy Class name of IPAProxy derived class to register * * Register a proxy subclass with the factory and make it available to * isolate IPA modules. */ } /* namespace libcamera */ '#n13'>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 94 95 96 97 98 99 100 101
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * stream_formats.cpp - StreamFormats test
 */

#include <iostream>

#include <libcamera/geometry.h>
#include <libcamera/stream.h>

#include "test.h"

using namespace std;
using namespace libcamera;

class StreamFormatsTest : public Test
{
protected:
	int testSizes(std::string name, std::vector<Size> test, std::vector<Size> valid)
	{
		bool pass = false;

		for (Size &size : test) {
			pass = false;

			for (Size &validSize : valid) {
				if (size == validSize) {
					pass = true;
					break;
				}
			}

			if (!pass)
				break;
		}

		if (!pass) {
			cout << "Failed " << name << endl;
			cout << "Sizes to test:" << endl;
			for (Size &size : test)
				cout << size.toString() << endl;
			cout << "Valid sizes:" << endl;
			for (Size &size : valid)
				cout << size.toString() << endl;

			return TestFail;
		}

		return TestPass;
	}

	int run()
	{
		/* Test discrete sizes */
		StreamFormats discrete({
			{ PixelFormat(1), { SizeRange({ 100, 100 }), SizeRange({ 200, 200 }) } },
			{ PixelFormat(2), { SizeRange({ 300, 300 }), SizeRange({ 400, 400 }) } },
		});

		if (testSizes("discrete 1", discrete.sizes(PixelFormat(1)),
			      { Size(100, 100), Size(200, 200) }))
			return TestFail;
		if (testSizes("discrete 2", discrete.sizes(PixelFormat(2)),
			      { Size(300, 300), Size(400, 400) }))
			return TestFail;

		/* Test range sizes */
		StreamFormats range({
			{ PixelFormat(1), { SizeRange({ 640, 480 }, { 640, 480 }) } },
			{ PixelFormat(2), { SizeRange({ 640, 480 }, { 800, 600 }, 8, 8) } },
			{ PixelFormat(3), { SizeRange({ 640, 480 }, { 800, 600 }, 16, 16) } },
			{ PixelFormat(4), { SizeRange({ 128, 128 }, { 4096, 4096 }, 128, 128) } },
		});

		if (testSizes("range 1", range.sizes(PixelFormat(1)), { Size(640, 480) }))
			return TestFail;

		if (testSizes("range 2", range.sizes(PixelFormat(2)), {
			      Size(640, 480), Size(720, 480),
			      Size(720, 576), Size(768, 480),
			      Size(800, 600) }))
			return TestFail;

		if (testSizes("range 3", range.sizes(PixelFormat(3)), {
			      Size(640, 480), Size(720, 480),
			      Size(720, 576), Size(768, 480) }))
			return TestFail;

		if (testSizes("range 4", range.sizes(PixelFormat(4)), {
			      Size(1024, 768), Size(1280, 1024),
			      Size(2048, 1152), Size(2048, 1536),
			      Size(2560, 2048), Size(3200, 2048), }))
			return TestFail;

		return TestPass;
	}
};

TEST_REGISTER(StreamFormatsTest)