Patch Detail
Show a patch.
GET /api/patches/11088/?format=api
{ "id": 11088, "url": "https://patchwork.libcamera.org/api/patches/11088/?format=api", "web_url": "https://patchwork.libcamera.org/patch/11088/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20210131224702.8838-10-laurent.pinchart@ideasonboard.com>", "date": "2021-01-31T22:46:51", "name": "[libcamera-devel,09/20] libcamera: pipeline: simple: converter: Add multi-stream support", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "3c613af1271cab493ba5eb94f104acddd2e5c2ca", "submitter": { "id": 2, "url": "https://patchwork.libcamera.org/api/people/2/?format=api", "name": "Laurent Pinchart", "email": "laurent.pinchart@ideasonboard.com" }, "delegate": { "id": 14, "url": "https://patchwork.libcamera.org/api/users/14/?format=api", "username": "pinchartl", "first_name": "Laurent", "last_name": "Pinchart", "email": "laurent.pinchart@ideasonboard.com" }, "mbox": "https://patchwork.libcamera.org/patch/11088/mbox/", "series": [ { "id": 1633, "url": "https://patchwork.libcamera.org/api/series/1633/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=1633", "date": "2021-01-31T22:46:42", "name": "[libcamera-devel,01/20] libcamera: pipeline: simple: Manage converter with std::unique_ptr<>", "version": 1, "mbox": "https://patchwork.libcamera.org/series/1633/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/11088/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/11088/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id DD64CBD808\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSun, 31 Jan 2021 22:47:40 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A7ECB68411;\n\tSun, 31 Jan 2021 23:47:40 +0100 (CET)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4F0CD683E0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 31 Jan 2021 23:47:31 +0100 (CET)", "from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id D68641460; \n\tSun, 31 Jan 2021 23:47:30 +0100 (CET)" ], "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"ut8M1lRa\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1612133251;\n\tbh=yFBWlz+JxVm2MSv9YLIAxbCUWjk9/213xueQ6ccIxbY=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=ut8M1lRa479kizbaWf0KULpMU9H4W6D8+tuh4/usdw5/Qe9cpo4rsJIlIVXXZqdhW\n\txxEVnBlw2uTXmG+/9r4AGvf4L5O5khr7WM/9wEtO+nawzDfMVj2c2ivO6DHqTh6PV8\n\tk0By56RyUUM2q2ac8aTLWt2fI2PPZ6JNgGVhEBuM=", "From": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Mon, 1 Feb 2021 00:46:51 +0200", "Message-Id": "<20210131224702.8838-10-laurent.pinchart@ideasonboard.com>", "X-Mailer": "git-send-email 2.28.0", "In-Reply-To": "<20210131224702.8838-1-laurent.pinchart@ideasonboard.com>", "References": "<20210131224702.8838-1-laurent.pinchart@ideasonboard.com>", "MIME-Version": "1.0", "Subject": "[libcamera-devel] [PATCH 09/20] libcamera: pipeline: simple:\n\tconverter: Add multi-stream support", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Cc": "Phi-Bang Nguyen <pnguyen@baylibre.com>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "While the M2M device backing the converter doesn't support multiple\nstreams natively, it can be run once per stream to produce multiple\noutputs from the same input, with different output formats and sizes.\n\nTo support this, create a class to model a stream and move control of\nthe M2M device to the Stream class. The SimpleConverter class then\ncreates stream instances and iterates over them. Each stream needs its\nown instance of the V4L2M2MDevice, to support different output\nconfigurations. The SimpleConverter class retains a device instance to\nsupport the query operations.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/libcamera/pipeline/simple/converter.cpp | 294 ++++++++++++++------\n src/libcamera/pipeline/simple/converter.h | 44 ++-\n src/libcamera/pipeline/simple/simple.cpp | 6 +-\n 3 files changed, 250 insertions(+), 94 deletions(-)", "diff": "diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp\nindex 8324baedc198..3db162d9edb8 100644\n--- a/src/libcamera/pipeline/simple/converter.cpp\n+++ b/src/libcamera/pipeline/simple/converter.cpp\n@@ -17,12 +17,157 @@\n \n #include \"libcamera/internal/log.h\"\n #include \"libcamera/internal/media_device.h\"\n+#include \"libcamera/internal/utils.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n \n namespace libcamera {\n \n LOG_DECLARE_CATEGORY(SimplePipeline)\n \n+/* -----------------------------------------------------------------------------\n+ * SimpleConverter::Stream\n+ */\n+\n+SimpleConverter::Stream::Stream(SimpleConverter *converter)\n+\t: converter_(converter)\n+{\n+\tm2m_ = std::make_unique<V4L2M2MDevice>(converter->deviceNode_);\n+\n+\tm2m_->output()->bufferReady.connect(this, &Stream::outputBufferReady);\n+\tm2m_->capture()->bufferReady.connect(this, &Stream::captureBufferReady);\n+\n+\tint ret = m2m_->open();\n+\tif (ret < 0)\n+\t\tm2m_.reset();\n+}\n+\n+int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n+\t\t\t\t const StreamConfiguration &outputCfg)\n+{\n+\tV4L2PixelFormat videoFormat =\n+\t\tm2m_->output()->toV4L2PixelFormat(inputCfg.pixelFormat);\n+\n+\tV4L2DeviceFormat format;\n+\tformat.fourcc = videoFormat;\n+\tformat.size = inputCfg.size;\n+\tformat.planesCount = 1;\n+\tformat.planes[0].bpl = inputCfg.stride;\n+\n+\tint ret = m2m_->output()->setFormat(&format);\n+\tif (ret < 0) {\n+\t\tLOG(SimplePipeline, Error)\n+\t\t\t<< \"Failed to set input format: \" << strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\tif (format.fourcc != videoFormat || format.size != inputCfg.size ||\n+\t format.planes[0].bpl != inputCfg.stride) {\n+\t\tLOG(SimplePipeline, Error)\n+\t\t\t<< \"Input format not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Set the pixel format and size on the output. */\n+\tvideoFormat = m2m_->capture()->toV4L2PixelFormat(outputCfg.pixelFormat);\n+\tformat = {};\n+\tformat.fourcc = videoFormat;\n+\tformat.size = outputCfg.size;\n+\n+\tret = m2m_->capture()->setFormat(&format);\n+\tif (ret < 0) {\n+\t\tLOG(SimplePipeline, Error)\n+\t\t\t<< \"Failed to set output format: \" << strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\tif (format.fourcc != videoFormat || format.size != outputCfg.size) {\n+\t\tLOG(SimplePipeline, Error)\n+\t\t\t<< \"Output format not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tinputBufferCount_ = inputCfg.bufferCount;\n+\toutputBufferCount_ = outputCfg.bufferCount;\n+\n+\treturn 0;\n+}\n+\n+int SimpleConverter::Stream::exportBuffers(unsigned int count,\n+\t\t\t\t\t std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n+{\n+\treturn m2m_->capture()->exportBuffers(count, buffers);\n+}\n+\n+int SimpleConverter::Stream::start()\n+{\n+\tint ret = m2m_->output()->importBuffers(inputBufferCount_);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = m2m_->capture()->importBuffers(outputBufferCount_);\n+\tif (ret < 0) {\n+\t\tstop();\n+\t\treturn ret;\n+\t}\n+\n+\tret = m2m_->output()->streamOn();\n+\tif (ret < 0) {\n+\t\tstop();\n+\t\treturn ret;\n+\t}\n+\n+\tret = m2m_->capture()->streamOn();\n+\tif (ret < 0) {\n+\t\tstop();\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void SimpleConverter::Stream::stop()\n+{\n+\tm2m_->capture()->streamOff();\n+\tm2m_->output()->streamOff();\n+\tm2m_->capture()->releaseBuffers();\n+\tm2m_->output()->releaseBuffers();\n+}\n+\n+int SimpleConverter::Stream::queueBuffers(FrameBuffer *input,\n+\t\t\t\t\t FrameBuffer *output)\n+{\n+\tint ret = m2m_->output()->queueBuffer(input);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = m2m_->capture()->queueBuffer(output);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\treturn 0;\n+}\n+\n+void SimpleConverter::Stream::outputBufferReady(FrameBuffer *buffer)\n+{\n+\tauto it = converter_->queue_.find(buffer);\n+\tif (it == converter_->queue_.end())\n+\t\treturn;\n+\n+\tif (!--it->second) {\n+\t\tconverter_->inputBufferReady.emit(buffer);\n+\t\tconverter_->queue_.erase(it);\n+\t}\n+}\n+\n+void SimpleConverter::Stream::captureBufferReady(FrameBuffer *buffer)\n+{\n+\tconverter_->outputBufferReady.emit(buffer);\n+}\n+\n+/* -----------------------------------------------------------------------------\n+ * SimpleConverter\n+ */\n+\n SimpleConverter::SimpleConverter(MediaDevice *media)\n {\n \t/*\n@@ -37,16 +182,14 @@ SimpleConverter::SimpleConverter(MediaDevice *media)\n \tif (it == entities.end())\n \t\treturn;\n \n-\tm2m_ = std::make_unique<V4L2M2MDevice>((*it)->deviceNode());\n+\tdeviceNode_ = (*it)->deviceNode();\n \n+\tm2m_ = std::make_unique<V4L2M2MDevice>(deviceNode_);\n \tint ret = m2m_->open();\n \tif (ret < 0) {\n \t\tm2m_.reset();\n \t\treturn;\n \t}\n-\n-\tm2m_->output()->bufferReady.connect(this, &SimpleConverter::m2mInputBufferReady);\n-\tm2m_->capture()->bufferReady.connect(this, &SimpleConverter::m2mOutputBufferReady);\n }\n \n std::vector<PixelFormat> SimpleConverter::formats(PixelFormat input)\n@@ -141,86 +284,54 @@ SimpleConverter::strideAndFrameSize(const PixelFormat &pixelFormat,\n }\n \n int SimpleConverter::configure(const StreamConfiguration &inputCfg,\n-\t\t\t const StreamConfiguration &outputCfg)\n+\t\t\t const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs)\n {\n-\tint ret;\n+\tint ret = 0;\n \n-\tV4L2PixelFormat videoFormat =\n-\t\tm2m_->output()->toV4L2PixelFormat(inputCfg.pixelFormat);\n+\tstreams_.clear();\n+\tstreams_.reserve(outputCfgs.size());\n \n-\tV4L2DeviceFormat format;\n-\tformat.fourcc = videoFormat;\n-\tformat.size = inputCfg.size;\n-\tformat.planesCount = 1;\n-\tformat.planes[0].bpl = inputCfg.stride;\n+\tfor (const StreamConfiguration &outputCfg : outputCfgs) {\n+\t\tStream &stream = streams_.emplace_back(this);\n \n-\tret = m2m_->output()->setFormat(&format);\n-\tif (ret < 0) {\n-\t\tLOG(SimplePipeline, Error)\n-\t\t\t<< \"Failed to set input format: \" << strerror(-ret);\n-\t\treturn ret;\n-\t}\n+\t\tif (!stream.isValid()) {\n+\t\t\tLOG(SimplePipeline, Error) << \"Failed to create stream\";\n+\t\t\tret = -EINVAL;\n+\t\t\tbreak;\n+\t\t}\n \n-\tif (format.fourcc != videoFormat || format.size != inputCfg.size ||\n-\t format.planes[0].bpl != inputCfg.stride) {\n-\t\tLOG(SimplePipeline, Error)\n-\t\t\t<< \"Input format not supported\";\n-\t\treturn -EINVAL;\n+\t\tret = stream.configure(inputCfg, outputCfg);\n+\t\tif (ret < 0)\n+\t\t\tbreak;\n \t}\n \n-\t/* Set the pixel format and size on the output. */\n-\tvideoFormat = m2m_->capture()->toV4L2PixelFormat(outputCfg.pixelFormat);\n-\tformat = {};\n-\tformat.fourcc = videoFormat;\n-\tformat.size = outputCfg.size;\n-\n-\tret = m2m_->capture()->setFormat(&format);\n \tif (ret < 0) {\n-\t\tLOG(SimplePipeline, Error)\n-\t\t\t<< \"Failed to set output format: \" << strerror(-ret);\n+\t\tstreams_.clear();\n \t\treturn ret;\n \t}\n \n-\tif (format.fourcc != videoFormat || format.size != outputCfg.size) {\n-\t\tLOG(SimplePipeline, Error)\n-\t\t\t<< \"Output format not supported\";\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tinputBufferCount_ = inputCfg.bufferCount;\n-\toutputBufferCount_ = outputCfg.bufferCount;\n-\n \treturn 0;\n }\n \n-int SimpleConverter::exportBuffers(unsigned int count,\n+int SimpleConverter::exportBuffers(unsigned int output, unsigned int count,\n \t\t\t\t std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n-\treturn m2m_->capture()->exportBuffers(count, buffers);\n+\tif (output >= streams_.size())\n+\t\treturn -EINVAL;\n+\n+\treturn streams_[output].exportBuffers(count, buffers);\n }\n \n int SimpleConverter::start()\n {\n-\tint ret = m2m_->output()->importBuffers(inputBufferCount_);\n-\tif (ret < 0)\n-\t\treturn ret;\n+\tint ret;\n \n-\tret = m2m_->capture()->importBuffers(outputBufferCount_);\n-\tif (ret < 0) {\n-\t\tstop();\n-\t\treturn ret;\n-\t}\n-\n-\tret = m2m_->output()->streamOn();\n-\tif (ret < 0) {\n-\t\tstop();\n-\t\treturn ret;\n-\t}\n-\n-\tret = m2m_->capture()->streamOn();\n-\tif (ret < 0) {\n-\t\tstop();\n-\t\treturn ret;\n+\tfor (Stream &stream : utils::reverse(streams_)) {\n+\t\tret = stream.start();\n+\t\tif (ret < 0) {\n+\t\t\tstop();\n+\t\t\treturn ret;\n+\t\t}\n \t}\n \n \treturn 0;\n@@ -228,33 +339,48 @@ int SimpleConverter::start()\n \n void SimpleConverter::stop()\n {\n-\tm2m_->capture()->streamOff();\n-\tm2m_->output()->streamOff();\n-\tm2m_->capture()->releaseBuffers();\n-\tm2m_->output()->releaseBuffers();\n+\tfor (Stream &stream : utils::reverse(streams_))\n+\t\tstream.stop();\n }\n \n-int SimpleConverter::queueBuffers(FrameBuffer *input, FrameBuffer *output)\n+int SimpleConverter::queueBuffers(FrameBuffer *input,\n+\t\t\t\t const std::map<unsigned int, FrameBuffer *> &outputs)\n {\n-\tint ret = m2m_->output()->queueBuffer(input);\n-\tif (ret < 0)\n-\t\treturn ret;\n+\tunsigned int mask = 0;\n+\tint ret;\n \n-\tret = m2m_->capture()->queueBuffer(output);\n-\tif (ret < 0)\n-\t\treturn ret;\n+\t/* Validate the outputs as a sanity check. */\n+\tif (outputs.empty())\n+\t\treturn -EINVAL;\n+\n+\tfor (auto [index, buffer] : outputs) {\n+\t\tif (index >= streams_.size())\n+\t\t\treturn -EINVAL;\n+\t\tif (mask & (1 << index))\n+\t\t\treturn -EINVAL;\n+\t\tif (!buffer)\n+\t\t\treturn -EINVAL;\n+\n+\t\tmask |= 1 << index;\n+\t}\n+\n+\t/* Queue the input and output buffers to all the streams. */\n+\tfor (auto [index, buffer] : outputs) {\n+\t\tret = streams_[index].queueBuffers(input, buffer);\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\t}\n+\n+\t/*\n+\t * Add the input buffer to the queue, with the number of streams as a\n+\t * reference count. Completion of the input buffer will be signalled by\n+\t * the stream that releases the last reference.\n+\t */\n+\tqueue_.emplace(std::piecewise_construct,\n+\t\t std::forward_as_tuple(input),\n+\t\t std::forward_as_tuple(outputs.size()));\n \n \treturn 0;\n }\n \n-void SimpleConverter::m2mInputBufferReady(FrameBuffer *buffer)\n-{\n-\tinputBufferReady.emit(buffer);\n-}\n-\n-void SimpleConverter::m2mOutputBufferReady(FrameBuffer *buffer)\n-{\n-\toutputBufferReady.emit(buffer);\n-}\n-\n } /* namespace libcamera */\ndiff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h\nindex 739b24df0200..176978eefe48 100644\n--- a/src/libcamera/pipeline/simple/converter.h\n+++ b/src/libcamera/pipeline/simple/converter.h\n@@ -8,7 +8,10 @@\n #ifndef __LIBCAMERA_PIPELINE_SIMPLE_CONVERTER_H__\n #define __LIBCAMERA_PIPELINE_SIMPLE_CONVERTER_H__\n \n+#include <functional>\n+#include <map>\n #include <memory>\n+#include <string>\n #include <tuple>\n #include <vector>\n \n@@ -37,26 +40,53 @@ public:\n \tstrideAndFrameSize(const PixelFormat &pixelFormat, const Size &size);\n \n \tint configure(const StreamConfiguration &inputCfg,\n-\t\t const StreamConfiguration &outputCfg);\n-\tint exportBuffers(unsigned int count,\n+\t\t const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfg);\n+\tint exportBuffers(unsigned int ouput, unsigned int count,\n \t\t\t std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n \n \tint start();\n \tvoid stop();\n \n-\tint queueBuffers(FrameBuffer *input, FrameBuffer *output);\n+\tint queueBuffers(FrameBuffer *input,\n+\t\t\t const std::map<unsigned int, FrameBuffer *> &outputs);\n \n \tSignal<FrameBuffer *> inputBufferReady;\n \tSignal<FrameBuffer *> outputBufferReady;\n \n private:\n-\tvoid m2mInputBufferReady(FrameBuffer *buffer);\n-\tvoid m2mOutputBufferReady(FrameBuffer *buffer);\n+\tclass Stream\n+\t{\n+\tpublic:\n+\t\tStream(SimpleConverter *converter);\n \n+\t\tbool isValid() const { return m2m_ != nullptr; }\n+\n+\t\tint configure(const StreamConfiguration &inputCfg,\n+\t\t\t const StreamConfiguration &outputCfg);\n+\t\tint exportBuffers(unsigned int count,\n+\t\t\t\t std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n+\n+\t\tint start();\n+\t\tvoid stop();\n+\n+\t\tint queueBuffers(FrameBuffer *input, FrameBuffer *output);\n+\n+\tprivate:\n+\t\tvoid captureBufferReady(FrameBuffer *buffer);\n+\t\tvoid outputBufferReady(FrameBuffer *buffer);\n+\n+\t\tSimpleConverter *converter_;\n+\t\tstd::unique_ptr<V4L2M2MDevice> m2m_;\n+\n+\t\tunsigned int inputBufferCount_;\n+\t\tunsigned int outputBufferCount_;\n+\t};\n+\n+\tstd::string deviceNode_;\n \tstd::unique_ptr<V4L2M2MDevice> m2m_;\n \n-\tunsigned int inputBufferCount_;\n-\tunsigned int outputBufferCount_;\n+\tstd::vector<Stream> streams_;\n+\tstd::map<FrameBuffer *, unsigned int> queue_;\n };\n \n } /* namespace libcamera */\ndiff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\nindex 7f9c57234256..b7a890ab772e 100644\n--- a/src/libcamera/pipeline/simple/simple.cpp\n+++ b/src/libcamera/pipeline/simple/simple.cpp\n@@ -610,7 +610,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n \t\tinputCfg.stride = captureFormat.planes[0].bpl;\n \t\tinputCfg.bufferCount = cfg.bufferCount;\n \n-\t\tret = converter_->configure(inputCfg, cfg);\n+\t\tret = converter_->configure(inputCfg, { cfg });\n \t\tif (ret < 0) {\n \t\t\tLOG(SimplePipeline, Error)\n \t\t\t\t<< \"Unable to configure converter\";\n@@ -636,7 +636,7 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,\n \t * whether the converter is used or not.\n \t */\n \tif (useConverter_)\n-\t\treturn converter_->exportBuffers(count, buffers);\n+\t\treturn converter_->exportBuffers(0, count, buffers);\n \telse\n \t\treturn data->video_->exportBuffers(count, buffers);\n }\n@@ -917,7 +917,7 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer)\n \t\tFrameBuffer *output = converterQueue_.front();\n \t\tconverterQueue_.pop();\n \n-\t\tconverter_->queueBuffers(buffer, output);\n+\t\tconverter_->queueBuffers(buffer, { { 0, output } });\n \t\treturn;\n \t}\n \n", "prefixes": [ "libcamera-devel", "09/20" ] }