libcamera: Refactor the camera configuration storage and API
Refactor the CameraConfiguration structure to not rely on Stream instances. This is a step towards making the camera configuration object more powerful with configuration validation using "try" semantics. The CameraConfiguration now exposes a simple vector-like API to access the contained stream configurations. Both operator[]() and at() are provided to access elements. The isEmpty() method is renamed to empty() and the methods reordered to match the std::vector class. As applications need access to the Stream instances associated with the configuration entries in order to associate buffers with streams when creating requests, expose the stream selected by the pipeline handler through a new StreamConfiguration::stream(). Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
parent
a40023e6cc
commit
77ae64eb24
14 changed files with 258 additions and 225 deletions
|
@ -25,30 +25,36 @@ class Request;
|
||||||
class CameraConfiguration
|
class CameraConfiguration
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = std::vector<Stream *>::iterator;
|
using iterator = std::vector<StreamConfiguration>::iterator;
|
||||||
using const_iterator = std::vector<Stream *>::const_iterator;
|
using const_iterator = std::vector<StreamConfiguration>::const_iterator;
|
||||||
|
|
||||||
CameraConfiguration();
|
CameraConfiguration();
|
||||||
|
|
||||||
iterator begin();
|
void addConfiguration(const StreamConfiguration &cfg);
|
||||||
iterator end();
|
|
||||||
const_iterator begin() const;
|
|
||||||
const_iterator end() const;
|
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
bool isEmpty() const;
|
|
||||||
|
StreamConfiguration &at(unsigned int index);
|
||||||
|
const StreamConfiguration &at(unsigned int index) const;
|
||||||
|
StreamConfiguration &operator[](unsigned int index)
|
||||||
|
{
|
||||||
|
return at(index);
|
||||||
|
}
|
||||||
|
const StreamConfiguration &operator[](unsigned int index) const
|
||||||
|
{
|
||||||
|
return at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin();
|
||||||
|
const_iterator begin() const;
|
||||||
|
iterator end();
|
||||||
|
const_iterator end() const;
|
||||||
|
|
||||||
|
bool empty() const;
|
||||||
std::size_t size() const;
|
std::size_t size() const;
|
||||||
|
|
||||||
Stream *front();
|
|
||||||
const Stream *front() const;
|
|
||||||
|
|
||||||
Stream *operator[](unsigned int index) const;
|
|
||||||
StreamConfiguration &operator[](Stream *stream);
|
|
||||||
const StreamConfiguration &operator[](Stream *stream) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Stream *> order_;
|
std::vector<StreamConfiguration> config_;
|
||||||
std::map<Stream *, StreamConfiguration> config_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Camera final
|
class Camera final
|
||||||
|
@ -72,7 +78,7 @@ public:
|
||||||
|
|
||||||
const std::set<Stream *> &streams() const;
|
const std::set<Stream *> &streams() const;
|
||||||
CameraConfiguration generateConfiguration(const StreamRoles &roles);
|
CameraConfiguration generateConfiguration(const StreamRoles &roles);
|
||||||
int configure(const CameraConfiguration &config);
|
int configure(CameraConfiguration &config);
|
||||||
|
|
||||||
int allocateBuffers();
|
int allocateBuffers();
|
||||||
int freeBuffers();
|
int freeBuffers();
|
||||||
|
|
|
@ -16,14 +16,26 @@
|
||||||
namespace libcamera {
|
namespace libcamera {
|
||||||
|
|
||||||
class Camera;
|
class Camera;
|
||||||
|
class Stream;
|
||||||
|
|
||||||
struct StreamConfiguration {
|
struct StreamConfiguration {
|
||||||
|
StreamConfiguration()
|
||||||
|
: stream_(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int pixelFormat;
|
unsigned int pixelFormat;
|
||||||
Size size;
|
Size size;
|
||||||
|
|
||||||
unsigned int bufferCount;
|
unsigned int bufferCount;
|
||||||
|
|
||||||
|
Stream *stream() const { return stream_; }
|
||||||
|
void setStream(Stream *stream) { stream_ = stream; }
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Stream *stream_;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum StreamRole {
|
enum StreamRole {
|
||||||
|
|
|
@ -89,12 +89,9 @@ static int prepareCameraConfig(CameraConfiguration *config)
|
||||||
{
|
{
|
||||||
StreamRoles roles;
|
StreamRoles roles;
|
||||||
|
|
||||||
streamInfo.clear();
|
|
||||||
|
|
||||||
/* If no configuration is provided assume a single video stream. */
|
/* If no configuration is provided assume a single video stream. */
|
||||||
if (!options.isSet(OptStream)) {
|
if (!options.isSet(OptStream)) {
|
||||||
*config = camera->generateConfiguration({ StreamRole::VideoRecording });
|
*config = camera->generateConfiguration({ StreamRole::VideoRecording });
|
||||||
streamInfo[config->front()] = "stream0";
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,27 +126,20 @@ static int prepareCameraConfig(CameraConfiguration *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply configuration explicitly requested. */
|
/* Apply configuration explicitly requested. */
|
||||||
CameraConfiguration::iterator it = config->begin();
|
unsigned int i = 0;
|
||||||
for (auto const &value : streamOptions) {
|
for (auto const &value : streamOptions) {
|
||||||
KeyValueParser::Options conf = value.toKeyValues();
|
KeyValueParser::Options conf = value.toKeyValues();
|
||||||
Stream *stream = *it;
|
StreamConfiguration &cfg = (*config)[i++];
|
||||||
it++;
|
|
||||||
|
|
||||||
if (conf.isSet("width"))
|
if (conf.isSet("width"))
|
||||||
(*config)[stream].size.width = conf["width"];
|
cfg.size.width = conf["width"];
|
||||||
|
|
||||||
if (conf.isSet("height"))
|
if (conf.isSet("height"))
|
||||||
(*config)[stream].size.height = conf["height"];
|
cfg.size.height = conf["height"];
|
||||||
|
|
||||||
/* TODO: Translate 4CC string to ID. */
|
/* TODO: Translate 4CC string to ID. */
|
||||||
if (conf.isSet("pixelformat"))
|
if (conf.isSet("pixelformat"))
|
||||||
(*config)[stream].pixelFormat = conf["pixelformat"];
|
cfg.pixelFormat = conf["pixelformat"];
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int index = 0;
|
|
||||||
for (Stream *stream : *config) {
|
|
||||||
streamInfo[stream] = "stream" + std::to_string(index);
|
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -216,6 +206,13 @@ static int capture()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
streamInfo.clear();
|
||||||
|
|
||||||
|
for (unsigned int index = 0; index < config.size(); ++index) {
|
||||||
|
StreamConfiguration &cfg = config[index];
|
||||||
|
streamInfo[cfg.stream()] = "stream" + std::to_string(index);
|
||||||
|
}
|
||||||
|
|
||||||
ret = camera->allocateBuffers();
|
ret = camera->allocateBuffers();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
std::cerr << "Failed to allocate buffers"
|
std::cerr << "Failed to allocate buffers"
|
||||||
|
@ -227,8 +224,10 @@ static int capture()
|
||||||
|
|
||||||
/* Identify the stream with the least number of buffers. */
|
/* Identify the stream with the least number of buffers. */
|
||||||
unsigned int nbuffers = UINT_MAX;
|
unsigned int nbuffers = UINT_MAX;
|
||||||
for (Stream *stream : config)
|
for (StreamConfiguration &cfg : config) {
|
||||||
|
Stream *stream = cfg.stream();
|
||||||
nbuffers = std::min(nbuffers, stream->bufferPool().count());
|
nbuffers = std::min(nbuffers, stream->bufferPool().count());
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: make cam tool smarter to support still capture by for
|
* TODO: make cam tool smarter to support still capture by for
|
||||||
|
@ -245,8 +244,10 @@ static int capture()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<Stream *, Buffer *> map;
|
std::map<Stream *, Buffer *> map;
|
||||||
for (Stream *stream : config)
|
for (StreamConfiguration &cfg : config) {
|
||||||
|
Stream *stream = cfg.stream();
|
||||||
map[stream] = &stream->bufferPool().buffers()[i];
|
map[stream] = &stream->bufferPool().buffers()[i];
|
||||||
|
}
|
||||||
|
|
||||||
ret = request->setBuffers(map);
|
ret = request->setBuffers(map);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|
|
@ -46,72 +46,40 @@ LOG_DECLARE_CATEGORY(Camera)
|
||||||
* \class CameraConfiguration
|
* \class CameraConfiguration
|
||||||
* \brief Hold configuration for streams of the camera
|
* \brief Hold configuration for streams of the camera
|
||||||
|
|
||||||
* The CameraConfiguration holds an ordered list of streams and their associated
|
* The CameraConfiguration holds an ordered list of stream configurations. It
|
||||||
* StreamConfiguration. From a data storage point of view, the class operates as
|
* supports iterators and operates as a vector of StreamConfiguration instances.
|
||||||
* a map of Stream pointers to StreamConfiguration, with entries accessed with
|
* The stream configurations are inserted by addConfiguration(), and the
|
||||||
* operator[](Stream *). Accessing an entry for a Stream pointer not yet stored
|
* operator[](int) returns a reference to the StreamConfiguration based on its
|
||||||
* in the configuration inserts a new empty entry.
|
* insertion index. Accessing a stream configuration with an invalid index
|
||||||
*
|
* results in undefined behaviour.
|
||||||
* The class also suppors iterators, and from that point of view operates as a
|
|
||||||
* vector of Stream pointers. The streams are iterated in insertion order, and
|
|
||||||
* the operator[](int) returns the Stream pointer based on its insertion index.
|
|
||||||
* Accessing a stream with an invalid index returns a null pointer.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \typedef CameraConfiguration::iterator
|
* \typedef CameraConfiguration::iterator
|
||||||
* \brief Iterator for the streams in the configuration
|
* \brief Iterator for the stream configurations in the camera configuration
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \typedef CameraConfiguration::const_iterator
|
* \typedef CameraConfiguration::const_iterator
|
||||||
* \brief Const iterator for the streams in the configuration
|
* \brief Const iterator for the stream configuration in the camera
|
||||||
|
* configuration
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Create an empty camera configuration
|
* \brief Create an empty camera configuration
|
||||||
*/
|
*/
|
||||||
CameraConfiguration::CameraConfiguration()
|
CameraConfiguration::CameraConfiguration()
|
||||||
: order_({}), config_({})
|
: config_({})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Retrieve an iterator to the first stream in the sequence
|
* \brief Add a stream configuration to the camera configuration
|
||||||
* \return An iterator to the first stream
|
* \param[in] cfg The stream configuration
|
||||||
*/
|
*/
|
||||||
std::vector<Stream *>::iterator CameraConfiguration::begin()
|
void CameraConfiguration::addConfiguration(const StreamConfiguration &cfg)
|
||||||
{
|
{
|
||||||
return order_.begin();
|
config_.push_back(cfg);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Retrieve an iterator pointing to the past-the-end stream in the
|
|
||||||
* sequence
|
|
||||||
* \return An iterator to the element following the last stream
|
|
||||||
*/
|
|
||||||
std::vector<Stream *>::iterator CameraConfiguration::end()
|
|
||||||
{
|
|
||||||
return order_.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Retrieve a const iterator to the first element of the streams
|
|
||||||
* \return A const iterator to the first stream
|
|
||||||
*/
|
|
||||||
std::vector<Stream *>::const_iterator CameraConfiguration::begin() const
|
|
||||||
{
|
|
||||||
return order_.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Retrieve a const iterator pointing to the past-the-end stream in the
|
|
||||||
* sequence
|
|
||||||
* \return A const iterator to the element following the last stream
|
|
||||||
*/
|
|
||||||
std::vector<Stream *>::const_iterator CameraConfiguration::end() const
|
|
||||||
{
|
|
||||||
return order_.end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,12 +93,10 @@ std::vector<Stream *>::const_iterator CameraConfiguration::end() const
|
||||||
*/
|
*/
|
||||||
bool CameraConfiguration::isValid() const
|
bool CameraConfiguration::isValid() const
|
||||||
{
|
{
|
||||||
if (isEmpty())
|
if (empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (auto const &it : config_) {
|
for (const StreamConfiguration &cfg : config_) {
|
||||||
const StreamConfiguration &cfg = it.second;
|
|
||||||
|
|
||||||
if (cfg.size.width == 0 || cfg.size.height == 0 ||
|
if (cfg.size.width == 0 || cfg.size.height == 0 ||
|
||||||
cfg.pixelFormat == 0 || cfg.bufferCount == 0)
|
cfg.pixelFormat == 0 || cfg.bufferCount == 0)
|
||||||
return false;
|
return false;
|
||||||
|
@ -139,13 +105,108 @@ bool CameraConfiguration::isValid() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve a reference to a stream configuration
|
||||||
|
* \param[in] index Numerical index
|
||||||
|
*
|
||||||
|
* The \a index represents the zero based insertion order of stream
|
||||||
|
* configuration into the camera configuration with addConfiguration(). Calling
|
||||||
|
* this method with an invalid index results in undefined behaviour.
|
||||||
|
*
|
||||||
|
* \return The stream configuration
|
||||||
|
*/
|
||||||
|
StreamConfiguration &CameraConfiguration::at(unsigned int index)
|
||||||
|
{
|
||||||
|
return config_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve a const reference to a stream configuration
|
||||||
|
* \param[in] index Numerical index
|
||||||
|
*
|
||||||
|
* The \a index represents the zero based insertion order of stream
|
||||||
|
* configuration into the camera configuration with addConfiguration(). Calling
|
||||||
|
* this method with an invalid index results in undefined behaviour.
|
||||||
|
*
|
||||||
|
* \return The stream configuration
|
||||||
|
*/
|
||||||
|
const StreamConfiguration &CameraConfiguration::at(unsigned int index) const
|
||||||
|
{
|
||||||
|
return config_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn StreamConfiguration &CameraConfiguration::operator[](unsigned int)
|
||||||
|
* \brief Retrieve a reference to a stream configuration
|
||||||
|
* \param[in] index Numerical index
|
||||||
|
*
|
||||||
|
* The \a index represents the zero based insertion order of stream
|
||||||
|
* configuration into the camera configuration with addConfiguration(). Calling
|
||||||
|
* this method with an invalid index results in undefined behaviour.
|
||||||
|
*
|
||||||
|
* \return The stream configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn const StreamConfiguration &CameraConfiguration::operator[](unsigned int) const
|
||||||
|
* \brief Retrieve a const reference to a stream configuration
|
||||||
|
* \param[in] index Numerical index
|
||||||
|
*
|
||||||
|
* The \a index represents the zero based insertion order of stream
|
||||||
|
* configuration into the camera configuration with addConfiguration(). Calling
|
||||||
|
* this method with an invalid index results in undefined behaviour.
|
||||||
|
*
|
||||||
|
* \return The stream configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve an iterator to the first stream configuration in the
|
||||||
|
* sequence
|
||||||
|
* \return An iterator to the first stream configuration
|
||||||
|
*/
|
||||||
|
CameraConfiguration::iterator CameraConfiguration::begin()
|
||||||
|
{
|
||||||
|
return config_.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve a const iterator to the first element of the stream
|
||||||
|
* configurations
|
||||||
|
* \return A const iterator to the first stream configuration
|
||||||
|
*/
|
||||||
|
CameraConfiguration::const_iterator CameraConfiguration::begin() const
|
||||||
|
{
|
||||||
|
return config_.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve an iterator pointing to the past-the-end stream
|
||||||
|
* configuration in the sequence
|
||||||
|
* \return An iterator to the element following the last stream configuration
|
||||||
|
*/
|
||||||
|
CameraConfiguration::iterator CameraConfiguration::end()
|
||||||
|
{
|
||||||
|
return config_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve a const iterator pointing to the past-the-end stream
|
||||||
|
* configuration in the sequence
|
||||||
|
* \return A const iterator to the element following the last stream
|
||||||
|
* configuration
|
||||||
|
*/
|
||||||
|
CameraConfiguration::const_iterator CameraConfiguration::end() const
|
||||||
|
{
|
||||||
|
return config_.end();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Check if the camera configuration is empty
|
* \brief Check if the camera configuration is empty
|
||||||
* \return True if the configuration is empty
|
* \return True if the configuration is empty
|
||||||
*/
|
*/
|
||||||
bool CameraConfiguration::isEmpty() const
|
bool CameraConfiguration::empty() const
|
||||||
{
|
{
|
||||||
return order_.empty();
|
return config_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -154,75 +215,7 @@ bool CameraConfiguration::isEmpty() const
|
||||||
*/
|
*/
|
||||||
std::size_t CameraConfiguration::size() const
|
std::size_t CameraConfiguration::size() const
|
||||||
{
|
{
|
||||||
return order_.size();
|
return config_.size();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Access the first stream in the configuration
|
|
||||||
* \return The first stream in the configuration
|
|
||||||
*/
|
|
||||||
Stream *CameraConfiguration::front()
|
|
||||||
{
|
|
||||||
return order_.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Access the first stream in the configuration
|
|
||||||
* \return The first const stream pointer in the configuration
|
|
||||||
*/
|
|
||||||
const Stream *CameraConfiguration::front() const
|
|
||||||
{
|
|
||||||
return order_.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Retrieve a stream pointer from index
|
|
||||||
* \param[in] index Numerical index
|
|
||||||
*
|
|
||||||
* The \a index represents the zero based insertion order of stream and stream
|
|
||||||
* configuration into the camera configuration.
|
|
||||||
*
|
|
||||||
* \return The stream pointer at index, or a nullptr if the index is out of
|
|
||||||
* bounds
|
|
||||||
*/
|
|
||||||
Stream *CameraConfiguration::operator[](unsigned int index) const
|
|
||||||
{
|
|
||||||
if (index >= order_.size())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return order_.at(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Retrieve a reference to a stream configuration
|
|
||||||
* \param[in] stream Stream to retrieve configuration for
|
|
||||||
*
|
|
||||||
* If the camera configuration does not yet contain a configuration for
|
|
||||||
* the requested stream, create and return an empty stream configuration.
|
|
||||||
*
|
|
||||||
* \return The configuration for the stream
|
|
||||||
*/
|
|
||||||
StreamConfiguration &CameraConfiguration::operator[](Stream *stream)
|
|
||||||
{
|
|
||||||
if (config_.find(stream) == config_.end())
|
|
||||||
order_.push_back(stream);
|
|
||||||
|
|
||||||
return config_[stream];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Retrieve a const reference to a stream configuration
|
|
||||||
* \param[in] stream Stream to retrieve configuration for
|
|
||||||
*
|
|
||||||
* No new stream configuration is created if called with \a stream that is not
|
|
||||||
* already part of the camera configuration, doing so is an invalid operation
|
|
||||||
* and results in undefined behaviour.
|
|
||||||
*
|
|
||||||
* \return The configuration for the stream
|
|
||||||
*/
|
|
||||||
const StreamConfiguration &CameraConfiguration::operator[](Stream *stream) const
|
|
||||||
{
|
|
||||||
return config_.at(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -561,13 +554,9 @@ Camera::generateConfiguration(const StreamRoles &roles)
|
||||||
CameraConfiguration config = pipe_->generateConfiguration(this, roles);
|
CameraConfiguration config = pipe_->generateConfiguration(this, roles);
|
||||||
|
|
||||||
std::ostringstream msg("streams configuration:", std::ios_base::ate);
|
std::ostringstream msg("streams configuration:", std::ios_base::ate);
|
||||||
unsigned int index = 0;
|
|
||||||
|
|
||||||
for (Stream *stream : config) {
|
for (unsigned int index = 0; index < config.size(); ++index)
|
||||||
const StreamConfiguration &cfg = config[stream];
|
msg << " (" << index << ") " << config[index].toString();
|
||||||
msg << " (" << index << ") " << cfg.toString();
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(Camera, Debug) << msg.str();
|
LOG(Camera, Debug) << msg.str();
|
||||||
|
|
||||||
|
@ -593,12 +582,15 @@ Camera::generateConfiguration(const StreamRoles &roles)
|
||||||
*
|
*
|
||||||
* This function affects the state of the camera, see \ref camera_operation.
|
* This function affects the state of the camera, see \ref camera_operation.
|
||||||
*
|
*
|
||||||
|
* Upon return the StreamConfiguration entries in \a config are associated with
|
||||||
|
* Stream instances which can be retrieved with StreamConfiguration::stream().
|
||||||
|
*
|
||||||
* \return 0 on success or a negative error code otherwise
|
* \return 0 on success or a negative error code otherwise
|
||||||
* \retval -ENODEV The camera has been disconnected from the system
|
* \retval -ENODEV The camera has been disconnected from the system
|
||||||
* \retval -EACCES The camera is not in a state where it can be configured
|
* \retval -EACCES The camera is not in a state where it can be configured
|
||||||
* \retval -EINVAL The configuration is not valid
|
* \retval -EINVAL The configuration is not valid
|
||||||
*/
|
*/
|
||||||
int Camera::configure(const CameraConfiguration &config)
|
int Camera::configure(CameraConfiguration &config)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -615,16 +607,11 @@ int Camera::configure(const CameraConfiguration &config)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream msg("configuring streams:", std::ios_base::ate);
|
std::ostringstream msg("configuring streams:", std::ios_base::ate);
|
||||||
unsigned int index = 0;
|
|
||||||
|
|
||||||
for (Stream *stream : config) {
|
for (unsigned int index = 0; index < config.size(); ++index) {
|
||||||
if (streams_.find(stream) == streams_.end())
|
StreamConfiguration &cfg = config[index];
|
||||||
return -EINVAL;
|
cfg.setStream(nullptr);
|
||||||
|
msg << " (" << index << ") " << cfg.toString();
|
||||||
const StreamConfiguration &cfg = config[stream];
|
|
||||||
msg << std::dec << " (" << index << ") " << cfg.toString();
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(Camera, Info) << msg.str();
|
LOG(Camera, Info) << msg.str();
|
||||||
|
@ -634,8 +621,11 @@ int Camera::configure(const CameraConfiguration &config)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
activeStreams_.clear();
|
activeStreams_.clear();
|
||||||
for (Stream *stream : config) {
|
for (const StreamConfiguration &cfg : config) {
|
||||||
const StreamConfiguration &cfg = config[stream];
|
Stream *stream = cfg.stream();
|
||||||
|
if (!stream)
|
||||||
|
LOG(Camera, Fatal)
|
||||||
|
<< "Pipeline handler failed to update stream configuration";
|
||||||
|
|
||||||
stream->configuration_ = cfg;
|
stream->configuration_ = cfg;
|
||||||
activeStreams_.insert(stream);
|
activeStreams_.insert(stream);
|
||||||
|
|
|
@ -62,7 +62,7 @@ public:
|
||||||
|
|
||||||
virtual CameraConfiguration
|
virtual CameraConfiguration
|
||||||
generateConfiguration(Camera *camera, const StreamRoles &roles) = 0;
|
generateConfiguration(Camera *camera, const StreamRoles &roles) = 0;
|
||||||
virtual int configure(Camera *camera, const CameraConfiguration &config) = 0;
|
virtual int configure(Camera *camera, CameraConfiguration &config) = 0;
|
||||||
|
|
||||||
virtual int allocateBuffers(Camera *camera,
|
virtual int allocateBuffers(Camera *camera,
|
||||||
const std::set<Stream *> &streams) = 0;
|
const std::set<Stream *> &streams) = 0;
|
||||||
|
|
|
@ -152,8 +152,7 @@ public:
|
||||||
|
|
||||||
CameraConfiguration
|
CameraConfiguration
|
||||||
generateConfiguration(Camera *camera, const StreamRoles &roles) override;
|
generateConfiguration(Camera *camera, const StreamRoles &roles) override;
|
||||||
int configure(Camera *camera,
|
int configure(Camera *camera, CameraConfiguration &config) override;
|
||||||
const CameraConfiguration &config) override;
|
|
||||||
|
|
||||||
int allocateBuffers(Camera *camera,
|
int allocateBuffers(Camera *camera,
|
||||||
const std::set<Stream *> &streams) override;
|
const std::set<Stream *> &streams) override;
|
||||||
|
@ -299,14 +298,13 @@ PipelineHandlerIPU3::generateConfiguration(Camera *camera,
|
||||||
cfg.pixelFormat = V4L2_PIX_FMT_NV12;
|
cfg.pixelFormat = V4L2_PIX_FMT_NV12;
|
||||||
cfg.bufferCount = IPU3_BUFFER_COUNT;
|
cfg.bufferCount = IPU3_BUFFER_COUNT;
|
||||||
|
|
||||||
config[stream] = cfg;
|
config.addConfiguration(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PipelineHandlerIPU3::configure(Camera *camera,
|
int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration &config)
|
||||||
const CameraConfiguration &config)
|
|
||||||
{
|
{
|
||||||
IPU3CameraData *data = cameraData(camera);
|
IPU3CameraData *data = cameraData(camera);
|
||||||
IPU3Stream *outStream = &data->outStream_;
|
IPU3Stream *outStream = &data->outStream_;
|
||||||
|
@ -318,9 +316,13 @@ int PipelineHandlerIPU3::configure(Camera *camera,
|
||||||
|
|
||||||
outStream->active_ = false;
|
outStream->active_ = false;
|
||||||
vfStream->active_ = false;
|
vfStream->active_ = false;
|
||||||
for (Stream *s : config) {
|
for (StreamConfiguration &cfg : config) {
|
||||||
IPU3Stream *stream = static_cast<IPU3Stream *>(s);
|
/*
|
||||||
const StreamConfiguration &cfg = config[stream];
|
* Pick a stream for the configuration entry.
|
||||||
|
* \todo: This is a naive temporary implementation that will be
|
||||||
|
* reworked when implementing camera configuration validation.
|
||||||
|
*/
|
||||||
|
IPU3Stream *stream = vfStream->active_ ? outStream : vfStream;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify that the requested size respects the IPU3 alignment
|
* Verify that the requested size respects the IPU3 alignment
|
||||||
|
@ -355,6 +357,7 @@ int PipelineHandlerIPU3::configure(Camera *camera,
|
||||||
sensorSize.height = cfg.size.height;
|
sensorSize.height = cfg.size.height;
|
||||||
|
|
||||||
stream->active_ = true;
|
stream->active_ = true;
|
||||||
|
cfg.setStream(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -379,10 +382,9 @@ int PipelineHandlerIPU3::configure(Camera *camera,
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Apply the format to the configured streams output devices. */
|
/* Apply the format to the configured streams output devices. */
|
||||||
for (Stream *s : config) {
|
for (StreamConfiguration &cfg : config) {
|
||||||
IPU3Stream *stream = static_cast<IPU3Stream *>(s);
|
IPU3Stream *stream = static_cast<IPU3Stream *>(cfg.stream());
|
||||||
|
ret = imgu->configureOutput(stream->device_, cfg);
|
||||||
ret = imgu->configureOutput(stream->device_, config[stream]);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -393,15 +395,13 @@ int PipelineHandlerIPU3::configure(Camera *camera,
|
||||||
* be at least one active stream in the configuration request).
|
* be at least one active stream in the configuration request).
|
||||||
*/
|
*/
|
||||||
if (!outStream->active_) {
|
if (!outStream->active_) {
|
||||||
ret = imgu->configureOutput(outStream->device_,
|
ret = imgu->configureOutput(outStream->device_, config[0]);
|
||||||
config[vfStream]);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vfStream->active_) {
|
if (!vfStream->active_) {
|
||||||
ret = imgu->configureOutput(vfStream->device_,
|
ret = imgu->configureOutput(vfStream->device_, config[0]);
|
||||||
config[outStream]);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,7 @@ public:
|
||||||
|
|
||||||
CameraConfiguration generateConfiguration(Camera *camera,
|
CameraConfiguration generateConfiguration(Camera *camera,
|
||||||
const StreamRoles &roles) override;
|
const StreamRoles &roles) override;
|
||||||
int configure(Camera *camera,
|
int configure(Camera *camera, CameraConfiguration &config) override;
|
||||||
const CameraConfiguration &config) override;
|
|
||||||
|
|
||||||
int allocateBuffers(Camera *camera,
|
int allocateBuffers(Camera *camera,
|
||||||
const std::set<Stream *> &streams) override;
|
const std::set<Stream *> &streams) override;
|
||||||
|
@ -117,16 +116,15 @@ CameraConfiguration PipelineHandlerRkISP1::generateConfiguration(Camera *camera,
|
||||||
cfg.size = data->sensor_->resolution();
|
cfg.size = data->sensor_->resolution();
|
||||||
cfg.bufferCount = RKISP1_BUFFER_COUNT;
|
cfg.bufferCount = RKISP1_BUFFER_COUNT;
|
||||||
|
|
||||||
config[&data->stream_] = cfg;
|
config.addConfiguration(cfg);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PipelineHandlerRkISP1::configure(Camera *camera,
|
int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration &config)
|
||||||
const CameraConfiguration &config)
|
|
||||||
{
|
{
|
||||||
RkISP1CameraData *data = cameraData(camera);
|
RkISP1CameraData *data = cameraData(camera);
|
||||||
const StreamConfiguration &cfg = config[&data->stream_];
|
StreamConfiguration &cfg = config[0];
|
||||||
CameraSensor *sensor = data->sensor_;
|
CameraSensor *sensor = data->sensor_;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -217,6 +215,8 @@ int PipelineHandlerRkISP1::configure(Camera *camera,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg.setStream(&data->stream_);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,7 @@ public:
|
||||||
|
|
||||||
CameraConfiguration
|
CameraConfiguration
|
||||||
generateConfiguration(Camera *camera, const StreamRoles &roles) override;
|
generateConfiguration(Camera *camera, const StreamRoles &roles) override;
|
||||||
int configure(Camera *camera,
|
int configure(Camera *camera, CameraConfiguration &config) override;
|
||||||
const CameraConfiguration &config) override;
|
|
||||||
|
|
||||||
int allocateBuffers(Camera *camera,
|
int allocateBuffers(Camera *camera,
|
||||||
const std::set<Stream *> &streams) override;
|
const std::set<Stream *> &streams) override;
|
||||||
|
@ -78,38 +77,38 @@ CameraConfiguration
|
||||||
PipelineHandlerUVC::generateConfiguration(Camera *camera,
|
PipelineHandlerUVC::generateConfiguration(Camera *camera,
|
||||||
const StreamRoles &roles)
|
const StreamRoles &roles)
|
||||||
{
|
{
|
||||||
UVCCameraData *data = cameraData(camera);
|
|
||||||
CameraConfiguration config;
|
CameraConfiguration config;
|
||||||
StreamConfiguration cfg{};
|
StreamConfiguration cfg;
|
||||||
|
|
||||||
cfg.pixelFormat = V4L2_PIX_FMT_YUYV;
|
cfg.pixelFormat = V4L2_PIX_FMT_YUYV;
|
||||||
cfg.size = { 640, 480 };
|
cfg.size = { 640, 480 };
|
||||||
cfg.bufferCount = 4;
|
cfg.bufferCount = 4;
|
||||||
|
|
||||||
config[&data->stream_] = cfg;
|
config.addConfiguration(cfg);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PipelineHandlerUVC::configure(Camera *camera,
|
int PipelineHandlerUVC::configure(Camera *camera, CameraConfiguration &config)
|
||||||
const CameraConfiguration &config)
|
|
||||||
{
|
{
|
||||||
UVCCameraData *data = cameraData(camera);
|
UVCCameraData *data = cameraData(camera);
|
||||||
const StreamConfiguration *cfg = &config[&data->stream_];
|
StreamConfiguration &cfg = config[0];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
V4L2DeviceFormat format = {};
|
V4L2DeviceFormat format = {};
|
||||||
format.fourcc = cfg->pixelFormat;
|
format.fourcc = cfg.pixelFormat;
|
||||||
format.size = cfg->size;
|
format.size = cfg.size;
|
||||||
|
|
||||||
ret = data->video_->setFormat(&format);
|
ret = data->video_->setFormat(&format);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (format.size != cfg->size ||
|
if (format.size != cfg.size ||
|
||||||
format.fourcc != cfg->pixelFormat)
|
format.fourcc != cfg.pixelFormat)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
cfg.setStream(&data->stream_);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,7 @@ public:
|
||||||
|
|
||||||
CameraConfiguration
|
CameraConfiguration
|
||||||
generateConfiguration(Camera *camera, const StreamRoles &roles) override;
|
generateConfiguration(Camera *camera, const StreamRoles &roles) override;
|
||||||
int configure(Camera *camera,
|
int configure(Camera *camera, CameraConfiguration &config) override;
|
||||||
const CameraConfiguration &config) override;
|
|
||||||
|
|
||||||
int allocateBuffers(Camera *camera,
|
int allocateBuffers(Camera *camera,
|
||||||
const std::set<Stream *> &streams) override;
|
const std::set<Stream *> &streams) override;
|
||||||
|
@ -78,38 +77,38 @@ CameraConfiguration
|
||||||
PipelineHandlerVimc::generateConfiguration(Camera *camera,
|
PipelineHandlerVimc::generateConfiguration(Camera *camera,
|
||||||
const StreamRoles &roles)
|
const StreamRoles &roles)
|
||||||
{
|
{
|
||||||
VimcCameraData *data = cameraData(camera);
|
|
||||||
CameraConfiguration config;
|
CameraConfiguration config;
|
||||||
StreamConfiguration cfg{};
|
StreamConfiguration cfg;
|
||||||
|
|
||||||
cfg.pixelFormat = V4L2_PIX_FMT_RGB24;
|
cfg.pixelFormat = V4L2_PIX_FMT_RGB24;
|
||||||
cfg.size = { 640, 480 };
|
cfg.size = { 640, 480 };
|
||||||
cfg.bufferCount = 4;
|
cfg.bufferCount = 4;
|
||||||
|
|
||||||
config[&data->stream_] = cfg;
|
config.addConfiguration(cfg);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PipelineHandlerVimc::configure(Camera *camera,
|
int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration &config)
|
||||||
const CameraConfiguration &config)
|
|
||||||
{
|
{
|
||||||
VimcCameraData *data = cameraData(camera);
|
VimcCameraData *data = cameraData(camera);
|
||||||
const StreamConfiguration *cfg = &config[&data->stream_];
|
StreamConfiguration &cfg = config[0];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
V4L2DeviceFormat format = {};
|
V4L2DeviceFormat format = {};
|
||||||
format.fourcc = cfg->pixelFormat;
|
format.fourcc = cfg.pixelFormat;
|
||||||
format.size = cfg->size;
|
format.size = cfg.size;
|
||||||
|
|
||||||
ret = data->video_->setFormat(&format);
|
ret = data->video_->setFormat(&format);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (format.size != cfg->size ||
|
if (format.size != cfg.size ||
|
||||||
format.fourcc != cfg->pixelFormat)
|
format.fourcc != cfg.pixelFormat)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
cfg.setStream(&data->stream_);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -255,6 +255,10 @@ void PipelineHandler::unlock()
|
||||||
* configuration of a subset of the streams can't be satisfied, the
|
* configuration of a subset of the streams can't be satisfied, the
|
||||||
* whole configuration is considered invalid.
|
* whole configuration is considered invalid.
|
||||||
*
|
*
|
||||||
|
* Once the configuration is validated and the camera configured, the pipeline
|
||||||
|
* handler shall associate a Stream instance to each StreamConfiguration entry
|
||||||
|
* in the CameraConfiguration with the StreamConfiguration::setStream() method.
|
||||||
|
*
|
||||||
* \return 0 on success or a negative error code otherwise
|
* \return 0 on success or a negative error code otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,28 @@ namespace libcamera {
|
||||||
* \brief Requested number of buffers to allocate for the stream
|
* \brief Requested number of buffers to allocate for the stream
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn StreamConfiguration::stream()
|
||||||
|
* \brief Retrieve the stream associated with the configuration
|
||||||
|
*
|
||||||
|
* When a camera is configured with Camera::configure() Stream instances are
|
||||||
|
* associated with each stream configuration entry. This method retrieves the
|
||||||
|
* associated Stream, which remains valid until the next call to
|
||||||
|
* Camera::configure() or Camera::release().
|
||||||
|
*
|
||||||
|
* \return The stream associated with the configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn StreamConfiguration::setStream()
|
||||||
|
* \brief Associate a stream with a configuration
|
||||||
|
*
|
||||||
|
* This method is meant for the PipelineHandler::configure() method and shall
|
||||||
|
* not be called by applications.
|
||||||
|
*
|
||||||
|
* \param[in] stream The stream
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Assemble and return a string describing the configuration
|
* \brief Assemble and return a string describing the configuration
|
||||||
*
|
*
|
||||||
|
|
|
@ -98,14 +98,14 @@ int MainWindow::startCapture()
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
config_ = camera_->generateConfiguration({ StreamRole::VideoRecording });
|
config_ = camera_->generateConfiguration({ StreamRole::VideoRecording });
|
||||||
Stream *stream = config_.front();
|
|
||||||
ret = camera_->configure(config_);
|
ret = camera_->configure(config_);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
std::cout << "Failed to configure camera" << std::endl;
|
std::cout << "Failed to configure camera" << std::endl;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StreamConfiguration &cfg = config_[stream];
|
const StreamConfiguration &cfg = config_[0];
|
||||||
|
Stream *stream = cfg.stream();
|
||||||
ret = viewfinder_->setFormat(cfg.pixelFormat, cfg.size.width,
|
ret = viewfinder_->setFormat(cfg.pixelFormat, cfg.size.width,
|
||||||
cfg.size.height);
|
cfg.size.height);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|
|
@ -44,8 +44,7 @@ protected:
|
||||||
{
|
{
|
||||||
CameraConfiguration config =
|
CameraConfiguration config =
|
||||||
camera_->generateConfiguration({ StreamRole::VideoRecording });
|
camera_->generateConfiguration({ StreamRole::VideoRecording });
|
||||||
Stream *stream = config.front();
|
StreamConfiguration *cfg = &config[0];
|
||||||
StreamConfiguration *cfg = &config[stream];
|
|
||||||
|
|
||||||
if (!config.isValid()) {
|
if (!config.isValid()) {
|
||||||
cout << "Failed to read default configuration" << endl;
|
cout << "Failed to read default configuration" << endl;
|
||||||
|
@ -67,6 +66,7 @@ protected:
|
||||||
return TestFail;
|
return TestFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stream *stream = cfg->stream();
|
||||||
BufferPool &pool = stream->bufferPool();
|
BufferPool &pool = stream->bufferPool();
|
||||||
std::vector<Request *> requests;
|
std::vector<Request *> requests;
|
||||||
for (Buffer &buffer : pool.buffers()) {
|
for (Buffer &buffer : pool.buffers()) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ protected:
|
||||||
{
|
{
|
||||||
CameraConfiguration config =
|
CameraConfiguration config =
|
||||||
camera_->generateConfiguration({ StreamRole::VideoRecording });
|
camera_->generateConfiguration({ StreamRole::VideoRecording });
|
||||||
StreamConfiguration *cfg = &config[config.front()];
|
StreamConfiguration *cfg = &config[0];
|
||||||
|
|
||||||
if (!config.isValid()) {
|
if (!config.isValid()) {
|
||||||
cout << "Failed to read default configuration" << endl;
|
cout << "Failed to read default configuration" << endl;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue