Files
external_libcamera/src/libcamera/converter.cpp
Laurent Pinchart a458eb1adf libcamera: Drop path prefix from Doxygen file directive
The Doxygen directive only requires qualifying header file names with a
path to differentiate between multiple header files with the same name.
Most file directives that refer to unambiguous files do not have a
libcamera/ and/or internal/ path prefix, but a few do, most likely due
to copy&paste. Drop the prefix in those few files for consistency.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2024-08-07 17:57:01 +03:00

336 lines
9.9 KiB
C++

/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright 2022 NXP
*
* Generic format converter interface
*/
#include "libcamera/internal/converter.h"
#include <algorithm>
#include <libcamera/base/log.h>
#include "libcamera/internal/media_device.h"
/**
* \file converter.h
* \brief Abstract converter
*/
namespace libcamera {
LOG_DEFINE_CATEGORY(Converter)
/**
* \class Converter
* \brief Abstract Base Class for converter
*
* The Converter class is an Abstract Base Class defining the interfaces of
* converter implementations.
*
* Converters offer scaling and pixel format conversion services on an input
* stream. The converter can output multiple streams with individual conversion
* parameters from the same input stream.
*/
/**
* \brief Construct a Converter instance
* \param[in] media The media device implementing the converter
*
* This searches for the entity implementing the data streaming function in the
* media graph entities and use its device node as the converter device node.
*/
Converter::Converter(MediaDevice *media)
{
const std::vector<MediaEntity *> &entities = media->entities();
auto it = std::find_if(entities.begin(), entities.end(),
[](MediaEntity *entity) {
return entity->function() == MEDIA_ENT_F_IO_V4L;
});
if (it == entities.end()) {
LOG(Converter, Error)
<< "No entity suitable for implementing a converter in "
<< media->driver() << " entities list.";
return;
}
deviceNode_ = (*it)->deviceNode();
}
Converter::~Converter()
{
}
/**
* \fn Converter::loadConfiguration()
* \brief Load converter configuration from file
* \param[in] filename The file name path
*
* Load converter dependent configuration parameters to apply on the hardware.
*
* \return 0 on success or a negative error code otherwise
*/
/**
* \fn Converter::isValid()
* \brief Check if the converter configuration is valid
* \return True is the converter is valid, false otherwise
*/
/**
* \fn Converter::formats()
* \brief Retrieve the list of supported pixel formats for an input pixel format
* \param[in] input Input pixel format to retrieve output pixel format list for
* \return The list of supported output pixel formats
*/
/**
* \fn Converter::sizes()
* \brief Retrieve the range of minimum and maximum output sizes for an input size
* \param[in] input Input stream size to retrieve range for
* \return A range of output image sizes
*/
/**
* \fn Converter::strideAndFrameSize()
* \brief Retrieve the output stride and frame size for an input configutation
* \param[in] pixelFormat Input stream pixel format
* \param[in] size Input stream size
* \return A tuple indicating the stride and frame size or an empty tuple on error
*/
/**
* \fn Converter::configure()
* \brief Configure a set of output stream conversion from an input stream
* \param[in] inputCfg Input stream configuration
* \param[out] outputCfgs A list of output stream configurations
* \return 0 on success or a negative error code otherwise
*/
/**
* \fn Converter::exportBuffers()
* \brief Export buffers from the converter device
* \param[in] stream Output stream pointer exporting the buffers
* \param[in] count Number of buffers to allocate
* \param[out] buffers Vector to store allocated buffers
*
* This function operates similarly to V4L2VideoDevice::exportBuffers() on the
* output stream indicated by the \a output.
*
* \return The number of allocated buffers on success or a negative error code
* otherwise
*/
/**
* \fn Converter::start()
* \brief Start the converter streaming operation
* \return 0 on success or a negative error code otherwise
*/
/**
* \fn Converter::stop()
* \brief Stop the converter streaming operation
*/
/**
* \fn Converter::queueBuffers()
* \brief Queue buffers to converter device
* \param[in] input The frame buffer to apply the conversion
* \param[out] outputs The container holding the output stream pointers and
* their respective frame buffer outputs.
*
* This function queues the \a input frame buffer on the output streams of the
* \a outputs map key and retrieve the output frame buffer indicated by the
* buffer map value.
*
* \return 0 on success or a negative error code otherwise
*/
/**
* \var Converter::inputBufferReady
* \brief A signal emitted when the input frame buffer completes
*/
/**
* \var Converter::outputBufferReady
* \brief A signal emitted on each frame buffer completion of the output queue
*/
/**
* \fn Converter::deviceNode()
* \brief The converter device node attribute accessor
* \return The converter device node string
*/
/**
* \class ConverterFactoryBase
* \brief Base class for converter factories
*
* The ConverterFactoryBase class is the base of all specializations of the
* ConverterFactory class template. It implements the factory registration,
* maintains a registry of factories, and provides access to the registered
* factories.
*/
/**
* \brief Construct a converter factory base
* \param[in] name Name of the converter class
* \param[in] compatibles Name aliases of the converter class
*
* Creating an instance of the factory base registers it with the global list of
* factories, accessible through the factories() function.
*
* The factory \a name is used as unique identifier. If the converter
* implementation fully relies on a generic framework, the name should be the
* same as the framework. Otherwise, if the implementation is specialized, the
* factory name should match the driver name implementing the function.
*
* The factory \a compatibles holds a list of driver names implementing a generic
* subsystem without any personalizations.
*/
ConverterFactoryBase::ConverterFactoryBase(const std::string name, std::initializer_list<std::string> compatibles)
: name_(name), compatibles_(compatibles)
{
registerType(this);
}
/**
* \fn ConverterFactoryBase::compatibles()
* \return The list of compatible name aliases of the converter
*/
/**
* \brief Create an instance of the converter corresponding to the media device
* \param[in] media The media device to create the converter for
*
* The converter is created by matching the factory name or any of its
* compatible aliases with the media device driver name.
*
* \return A new instance of the converter subclass corresponding to the media
* device, or null if the media device driver name doesn't match anything
*/
std::unique_ptr<Converter> ConverterFactoryBase::create(MediaDevice *media)
{
const std::vector<ConverterFactoryBase *> &factories =
ConverterFactoryBase::factories();
for (const ConverterFactoryBase *factory : factories) {
const std::vector<std::string> &compatibles = factory->compatibles();
auto it = std::find(compatibles.begin(), compatibles.end(), media->driver());
if (it == compatibles.end() && media->driver() != factory->name_)
continue;
LOG(Converter, Debug)
<< "Creating converter from "
<< factory->name_ << " factory with "
<< (it == compatibles.end() ? "no" : media->driver()) << " alias.";
std::unique_ptr<Converter> converter = factory->createInstance(media);
if (converter->isValid())
return converter;
}
return nullptr;
}
/**
* \brief Add a converter factory to the registry
* \param[in] factory Factory to use to construct the converter class
*
* The caller is responsible to guarantee the uniqueness of the converter
* factory name.
*/
void ConverterFactoryBase::registerType(ConverterFactoryBase *factory)
{
std::vector<ConverterFactoryBase *> &factories =
ConverterFactoryBase::factories();
factories.push_back(factory);
}
/**
* \brief Retrieve the list of all converter factory names
* \return The list of all converter factory names
*/
std::vector<std::string> ConverterFactoryBase::names()
{
std::vector<std::string> list;
std::vector<ConverterFactoryBase *> &factories =
ConverterFactoryBase::factories();
for (ConverterFactoryBase *factory : factories) {
list.push_back(factory->name_);
for (auto alias : factory->compatibles())
list.push_back(alias);
}
return list;
}
/**
* \brief Retrieve the list of all converter factories
* \return The list of converter factories
*/
std::vector<ConverterFactoryBase *> &ConverterFactoryBase::factories()
{
/*
* The static factories map is defined inside the function to ensure
* it gets initialized on first use, without any dependency on link
* order.
*/
static std::vector<ConverterFactoryBase *> factories;
return factories;
}
/**
* \var ConverterFactoryBase::name_
* \brief The name of the factory
*/
/**
* \var ConverterFactoryBase::compatibles_
* \brief The list holding the factory compatibles
*/
/**
* \class ConverterFactory
* \brief Registration of ConverterFactory classes and creation of instances
* \param _Converter The converter class type for this factory
*
* To facilitate discovery and instantiation of Converter classes, the
* ConverterFactory class implements auto-registration of converter helpers.
* Each Converter subclass shall register itself using the REGISTER_CONVERTER()
* macro, which will create a corresponding instance of a ConverterFactory
* subclass and register it with the static list of factories.
*/
/**
* \fn ConverterFactory::ConverterFactory(const char *name, std::initializer_list<std::string> compatibles)
* \brief Construct a converter factory
* \details \copydetails ConverterFactoryBase::ConverterFactoryBase
*/
/**
* \fn ConverterFactory::createInstance() const
* \brief Create an instance of the Converter corresponding to the factory
* \param[in] media Media device pointer
* \return A unique pointer to a newly constructed instance of the Converter
* subclass corresponding to the factory
*/
/**
* \def REGISTER_CONVERTER
* \brief Register a converter with the Converter factory
* \param[in] name Converter name used to register the class
* \param[in] converter Class name of Converter derived class to register
* \param[in] compatibles List of compatible names
*
* Register a Converter subclass with the factory and make it available to try
* and match converters.
*/
} /* namespace libcamera */