diff options
-rw-r--r-- | include/libcamera/internal/converter/converter_v4l2_m2m.h (renamed from src/libcamera/pipeline/simple/converter.h) | 22 | ||||
-rw-r--r-- | include/libcamera/internal/converter/meson.build | 5 | ||||
-rw-r--r-- | include/libcamera/internal/meson.build | 2 | ||||
-rw-r--r-- | src/libcamera/converter/converter_v4l2_m2m.cpp (renamed from src/libcamera/pipeline/simple/converter.cpp) | 156 | ||||
-rw-r--r-- | src/libcamera/converter/meson.build | 5 | ||||
-rw-r--r-- | src/libcamera/meson.build | 1 | ||||
-rw-r--r-- | src/libcamera/pipeline/simple/meson.build | 1 | ||||
-rw-r--r-- | src/libcamera/pipeline/simple/simple.cpp | 6 |
8 files changed, 129 insertions, 69 deletions
diff --git a/src/libcamera/pipeline/simple/converter.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h index f0ebe2e0..815916d0 100644 --- a/src/libcamera/pipeline/simple/converter.h +++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h @@ -1,8 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2020, Laurent Pinchart + * Copyright 2022 NXP * - * converter.h - Format converter for simple pipeline handler + * converter_v4l2_m2m.h - V4l2 M2M Format converter interface */ #pragma once @@ -14,11 +15,13 @@ #include <tuple> #include <vector> -#include <libcamera/pixel_format.h> - #include <libcamera/base/log.h> #include <libcamera/base/signal.h> +#include <libcamera/pixel_format.h> + +#include "libcamera/internal/converter.h" + namespace libcamera { class FrameBuffer; @@ -28,11 +31,12 @@ class SizeRange; struct StreamConfiguration; class V4L2M2MDevice; -class SimpleConverter +class V4L2M2MConverter : public Converter { public: - SimpleConverter(MediaDevice *media); + V4L2M2MConverter(MediaDevice *media); + int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; } bool isValid() const { return m2m_ != nullptr; } std::vector<PixelFormat> formats(PixelFormat input); @@ -52,14 +56,11 @@ public: int queueBuffers(FrameBuffer *input, const std::map<unsigned int, FrameBuffer *> &outputs); - Signal<FrameBuffer *> inputBufferReady; - Signal<FrameBuffer *> outputBufferReady; - private: class Stream : protected Loggable { public: - Stream(SimpleConverter *converter, unsigned int index); + Stream(V4L2M2MConverter *converter, unsigned int index); bool isValid() const { return m2m_ != nullptr; } @@ -80,7 +81,7 @@ private: void captureBufferReady(FrameBuffer *buffer); void outputBufferReady(FrameBuffer *buffer); - SimpleConverter *converter_; + V4L2M2MConverter *converter_; unsigned int index_; std::unique_ptr<V4L2M2MDevice> m2m_; @@ -88,7 +89,6 @@ private: unsigned int outputBufferCount_; }; - std::string deviceNode_; std::unique_ptr<V4L2M2MDevice> m2m_; std::vector<Stream> streams_; diff --git a/include/libcamera/internal/converter/meson.build b/include/libcamera/internal/converter/meson.build new file mode 100644 index 00000000..891e79e7 --- /dev/null +++ b/include/libcamera/internal/converter/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: CC0-1.0 + +libcamera_internal_headers += files([ + 'converter_v4l2_m2m.h', +]) diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 341af8a2..d7508805 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -45,3 +45,5 @@ libcamera_internal_headers = files([ 'v4l2_videodevice.h', 'yaml_parser.h', ]) + +subdir('converter') diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp index acaaa64c..2a4d1d99 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/converter/converter_v4l2_m2m.cpp @@ -1,11 +1,12 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2020, Laurent Pinchart + * Copyright 2022 NXP * - * converter.cpp - Format converter for simple pipeline handler + * converter_v4l2_m2m.cpp - V4L2 M2M Format converter */ -#include "converter.h" +#include "libcamera/internal/converter/converter_v4l2_m2m.h" #include <algorithm> #include <limits.h> @@ -21,18 +22,23 @@ #include "libcamera/internal/media_device.h" #include "libcamera/internal/v4l2_videodevice.h" +/** + * \file internal/converter/converter_v4l2_m2m.h + * \brief V4L2 M2M based converter + */ + namespace libcamera { -LOG_DECLARE_CATEGORY(SimplePipeline) +LOG_DECLARE_CATEGORY(Converter) /* ----------------------------------------------------------------------------- - * SimpleConverter::Stream + * V4L2M2MConverter::Stream */ -SimpleConverter::Stream::Stream(SimpleConverter *converter, unsigned int index) +V4L2M2MConverter::Stream::Stream(V4L2M2MConverter *converter, unsigned int index) : converter_(converter), index_(index) { - m2m_ = std::make_unique<V4L2M2MDevice>(converter->deviceNode_); + m2m_ = std::make_unique<V4L2M2MDevice>(converter->deviceNode()); m2m_->output()->bufferReady.connect(this, &Stream::outputBufferReady); m2m_->capture()->bufferReady.connect(this, &Stream::captureBufferReady); @@ -42,8 +48,8 @@ SimpleConverter::Stream::Stream(SimpleConverter *converter, unsigned int index) m2m_.reset(); } -int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, - const StreamConfiguration &outputCfg) +int V4L2M2MConverter::Stream::configure(const StreamConfiguration &inputCfg, + const StreamConfiguration &outputCfg) { V4L2PixelFormat videoFormat = m2m_->output()->toV4L2PixelFormat(inputCfg.pixelFormat); @@ -56,14 +62,14 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, int ret = m2m_->output()->setFormat(&format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to set input format: " << strerror(-ret); return ret; } if (format.fourcc != videoFormat || format.size != inputCfg.size || format.planes[0].bpl != inputCfg.stride) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Input format not supported (requested " << inputCfg.size << "-" << videoFormat << ", got " << format << ")"; @@ -78,13 +84,13 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, ret = m2m_->capture()->setFormat(&format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to set output format: " << strerror(-ret); return ret; } if (format.fourcc != videoFormat || format.size != outputCfg.size) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Output format not supported"; return -EINVAL; } @@ -95,13 +101,13 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, return 0; } -int SimpleConverter::Stream::exportBuffers(unsigned int count, - std::vector<std::unique_ptr<FrameBuffer>> *buffers) +int V4L2M2MConverter::Stream::exportBuffers(unsigned int count, + std::vector<std::unique_ptr<FrameBuffer>> *buffers) { return m2m_->capture()->exportBuffers(count, buffers); } -int SimpleConverter::Stream::start() +int V4L2M2MConverter::Stream::start() { int ret = m2m_->output()->importBuffers(inputBufferCount_); if (ret < 0) @@ -128,7 +134,7 @@ int SimpleConverter::Stream::start() return 0; } -void SimpleConverter::Stream::stop() +void V4L2M2MConverter::Stream::stop() { m2m_->capture()->streamOff(); m2m_->output()->streamOff(); @@ -136,8 +142,7 @@ void SimpleConverter::Stream::stop() m2m_->output()->releaseBuffers(); } -int SimpleConverter::Stream::queueBuffers(FrameBuffer *input, - FrameBuffer *output) +int V4L2M2MConverter::Stream::queueBuffers(FrameBuffer *input, FrameBuffer *output) { int ret = m2m_->output()->queueBuffer(input); if (ret < 0) @@ -150,12 +155,12 @@ int SimpleConverter::Stream::queueBuffers(FrameBuffer *input, return 0; } -std::string SimpleConverter::Stream::logPrefix() const +std::string V4L2M2MConverter::Stream::logPrefix() const { return "stream" + std::to_string(index_); } -void SimpleConverter::Stream::outputBufferReady(FrameBuffer *buffer) +void V4L2M2MConverter::Stream::outputBufferReady(FrameBuffer *buffer) { auto it = converter_->queue_.find(buffer); if (it == converter_->queue_.end()) @@ -167,32 +172,34 @@ void SimpleConverter::Stream::outputBufferReady(FrameBuffer *buffer) } } -void SimpleConverter::Stream::captureBufferReady(FrameBuffer *buffer) +void V4L2M2MConverter::Stream::captureBufferReady(FrameBuffer *buffer) { converter_->outputBufferReady.emit(buffer); } /* ----------------------------------------------------------------------------- - * SimpleConverter + * V4L2M2MConverter + */ + +/** + * \class libcamera::V4L2M2MConverter + * \brief The V4L2 M2M converter implements the converter interface based on + * V4L2 M2M device. +*/ + +/** + * \fn V4L2M2MConverter::V4L2M2MConverter + * \brief Construct a V4L2M2MConverter instance + * \param[in] media The media device implementing the converter */ -SimpleConverter::SimpleConverter(MediaDevice *media) +V4L2M2MConverter::V4L2M2MConverter(MediaDevice *media) + : Converter(media) { - /* - * Locate the video node. There's no need to validate the pipeline - * further, the caller guarantees that this is a V4L2 mem2mem device. - */ - 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()) + if (deviceNode().empty()) return; - deviceNode_ = (*it)->deviceNode(); - - m2m_ = std::make_unique<V4L2M2MDevice>(deviceNode_); + m2m_ = std::make_unique<V4L2M2MDevice>(deviceNode()); int ret = m2m_->open(); if (ret < 0) { m2m_.reset(); @@ -200,7 +207,21 @@ SimpleConverter::SimpleConverter(MediaDevice *media) } } -std::vector<PixelFormat> SimpleConverter::formats(PixelFormat input) +/** + * \fn libcamera::V4L2M2MConverter::loadConfiguration + * \details \copydetails libcamera::Converter::loadConfiguration + */ + +/** + * \fn libcamera::V4L2M2MConverter::isValid + * \details \copydetails libcamera::Converter::isValid + */ + +/** + * \fn libcamera::V4L2M2MConverter::formats + * \details \copydetails libcamera::Converter::formats + */ +std::vector<PixelFormat> V4L2M2MConverter::formats(PixelFormat input) { if (!m2m_) return {}; @@ -215,13 +236,13 @@ std::vector<PixelFormat> SimpleConverter::formats(PixelFormat input) int ret = m2m_->output()->setFormat(&v4l2Format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to set format: " << strerror(-ret); return {}; } if (v4l2Format.fourcc != m2m_->output()->toV4L2PixelFormat(input)) { - LOG(SimplePipeline, Debug) + LOG(Converter, Debug) << "Input format " << input << " not supported."; return {}; } @@ -237,7 +258,10 @@ std::vector<PixelFormat> SimpleConverter::formats(PixelFormat input) return pixelFormats; } -SizeRange SimpleConverter::sizes(const Size &input) +/** + * \copydoc libcamera::Converter::sizes + */ +SizeRange V4L2M2MConverter::sizes(const Size &input) { if (!m2m_) return {}; @@ -252,7 +276,7 @@ SizeRange SimpleConverter::sizes(const Size &input) int ret = m2m_->output()->setFormat(&format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to set format: " << strerror(-ret); return {}; } @@ -262,7 +286,7 @@ SizeRange SimpleConverter::sizes(const Size &input) format.size = { 1, 1 }; ret = m2m_->capture()->setFormat(&format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to set format: " << strerror(-ret); return {}; } @@ -272,7 +296,7 @@ SizeRange SimpleConverter::sizes(const Size &input) format.size = { UINT_MAX, UINT_MAX }; ret = m2m_->capture()->setFormat(&format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to set format: " << strerror(-ret); return {}; } @@ -282,9 +306,12 @@ SizeRange SimpleConverter::sizes(const Size &input) return sizes; } +/** + * \copydoc libcamera::Converter::strideAndFrameSize + */ std::tuple<unsigned int, unsigned int> -SimpleConverter::strideAndFrameSize(const PixelFormat &pixelFormat, - const Size &size) +V4L2M2MConverter::strideAndFrameSize(const PixelFormat &pixelFormat, + const Size &size) { V4L2DeviceFormat format; format.fourcc = m2m_->capture()->toV4L2PixelFormat(pixelFormat); @@ -297,8 +324,11 @@ SimpleConverter::strideAndFrameSize(const PixelFormat &pixelFormat, return std::make_tuple(format.planes[0].bpl, format.planes[0].size); } -int SimpleConverter::configure(const StreamConfiguration &inputCfg, - const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs) +/** + * \copydoc libcamera::Converter::configure + */ +int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg, + const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs) { int ret = 0; @@ -309,7 +339,7 @@ int SimpleConverter::configure(const StreamConfiguration &inputCfg, Stream &stream = streams_.emplace_back(this, i); if (!stream.isValid()) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to create stream " << i; ret = -EINVAL; break; @@ -328,8 +358,11 @@ int SimpleConverter::configure(const StreamConfiguration &inputCfg, return 0; } -int SimpleConverter::exportBuffers(unsigned int output, unsigned int count, - std::vector<std::unique_ptr<FrameBuffer>> *buffers) +/** + * \copydoc libcamera::Converter::exportBuffers + */ +int V4L2M2MConverter::exportBuffers(unsigned int output, unsigned int count, + std::vector<std::unique_ptr<FrameBuffer>> *buffers) { if (output >= streams_.size()) return -EINVAL; @@ -337,7 +370,10 @@ int SimpleConverter::exportBuffers(unsigned int output, unsigned int count, return streams_[output].exportBuffers(count, buffers); } -int SimpleConverter::start() +/** + * \copydoc libcamera::Converter::start + */ +int V4L2M2MConverter::start() { int ret; @@ -352,14 +388,20 @@ int SimpleConverter::start() return 0; } -void SimpleConverter::stop() +/** + * \copydoc libcamera::Converter::stop + */ +void V4L2M2MConverter::stop() { for (Stream &stream : utils::reverse(streams_)) stream.stop(); } -int SimpleConverter::queueBuffers(FrameBuffer *input, - const std::map<unsigned int, FrameBuffer *> &outputs) +/** + * \copydoc libcamera::Converter::queueBuffers + */ +int V4L2M2MConverter::queueBuffers(FrameBuffer *input, + const std::map<unsigned int, FrameBuffer *> &outputs) { unsigned int mask = 0; int ret; @@ -402,4 +444,10 @@ int SimpleConverter::queueBuffers(FrameBuffer *input, return 0; } +static std::initializer_list<std::string> compatibles = { + "pxp", +}; + +REGISTER_CONVERTER("v4l2_m2m", V4L2M2MConverter, compatibles) + } /* namespace libcamera */ diff --git a/src/libcamera/converter/meson.build b/src/libcamera/converter/meson.build new file mode 100644 index 00000000..2aa72fe4 --- /dev/null +++ b/src/libcamera/converter/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: CC0-1.0 + +libcamera_sources += files([ + 'converter_v4l2_m2m.cpp' +]) diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index e9d0324e..ffc294f3 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -62,6 +62,7 @@ libatomic = cc.find_library('atomic', required : false) libthreads = dependency('threads') subdir('base') +subdir('converter') subdir('ipa') subdir('pipeline') subdir('proxy') diff --git a/src/libcamera/pipeline/simple/meson.build b/src/libcamera/pipeline/simple/meson.build index 9c99b32f..42b0896d 100644 --- a/src/libcamera/pipeline/simple/meson.build +++ b/src/libcamera/pipeline/simple/meson.build @@ -1,6 +1,5 @@ # SPDX-License-Identifier: CC0-1.0 libcamera_sources += files([ - 'converter.cpp', 'simple.cpp', ]) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index a32de7f3..24ded4db 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -30,13 +30,13 @@ #include "libcamera/internal/camera.h" #include "libcamera/internal/camera_sensor.h" +#include "libcamera/internal/converter.h" #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" #include "libcamera/internal/v4l2_subdevice.h" #include "libcamera/internal/v4l2_videodevice.h" -#include "converter.h" namespace libcamera { @@ -266,7 +266,7 @@ public: std::vector<Configuration> configs_; std::map<PixelFormat, std::vector<const Configuration *>> formats_; - std::unique_ptr<SimpleConverter> converter_; + std::unique_ptr<Converter> converter_; std::vector<std::unique_ptr<FrameBuffer>> converterBuffers_; bool useConverter_; std::queue<std::map<unsigned int, FrameBuffer *>> converterQueue_; @@ -492,7 +492,7 @@ int SimpleCameraData::init() /* Open the converter, if any. */ MediaDevice *converter = pipe->converter(); if (converter) { - converter_ = std::make_unique<SimpleConverter>(converter); + converter_ = ConverterFactoryBase::create(converter); if (!converter_->isValid()) { LOG(SimplePipeline, Warning) << "Failed to create converter, disabling format conversion"; |