[{"id":29651,"web_url":"https://patchwork.libcamera.org/comment/29651/","msgid":"<171697681598.2248009.3497432656697474058@ping.linuxembedded.co.uk>","date":"2024-05-29T10:00:15","subject":"Re: [PATCH v2 4/4] libcamera: converter: Replace usage of stream\n\tindex by Stream pointer","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Umang Jain (2024-05-29 08:02:48)\n> The converter interface uses the unsigned int output stream index to map\n> to the output frame buffers. This is cumbersome to implement new\n> converters because one has to keep around additional book keeping\n> to track the streams with their correct indexes.\n> \n> The v4l2_converter_m2m and simple pipeline handler are adapted to\n> use the new interface. This work roped in software ISP as well,\n> which also seems to use indexes (although it doesn't implement converter\n> interface) because of a common conversionQueue_ queue used for\n> converter_ and swIsp_.\n\nUnfortunately - this patch breaks the SoftISP on Lenovo-X13s presently.\n\nI haven't looked into why yet, just that it breaks the camera.\n\n--\nKieran\n\n\n> \n> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n> ---\n>  include/libcamera/internal/converter.h        |  5 ++-\n>  .../internal/converter/converter_v4l2_m2m.h   | 11 ++---\n>  .../internal/software_isp/software_isp.h      |  5 ++-\n>  .../converter/converter_v4l2_m2m.cpp          | 40 ++++++++++---------\n>  src/libcamera/pipeline/simple/simple.cpp      | 14 +++----\n>  src/libcamera/software_isp/software_isp.cpp   | 13 +++---\n>  6 files changed, 46 insertions(+), 42 deletions(-)\n> \n> diff --git a/include/libcamera/internal/converter.h b/include/libcamera/internal/converter.h\n> index 5d74db6b..b51563d7 100644\n> --- a/include/libcamera/internal/converter.h\n> +++ b/include/libcamera/internal/converter.h\n> @@ -26,6 +26,7 @@ namespace libcamera {\n>  class FrameBuffer;\n>  class MediaDevice;\n>  class PixelFormat;\n> +class Stream;\n>  struct StreamConfiguration;\n>  \n>  class Converter\n> @@ -46,14 +47,14 @@ public:\n>  \n>         virtual int configure(const StreamConfiguration &inputCfg,\n>                               const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs) = 0;\n> -       virtual int exportBuffers(unsigned int output, unsigned int count,\n> +       virtual int exportBuffers(const Stream *stream, unsigned int count,\n>                                   std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;\n>  \n>         virtual int start() = 0;\n>         virtual void stop() = 0;\n>  \n>         virtual int queueBuffers(FrameBuffer *input,\n> -                                const std::map<unsigned int, FrameBuffer *> &outputs) = 0;\n> +                                const std::map<const Stream *, FrameBuffer *> &outputs) = 0;\n>  \n>         Signal<FrameBuffer *> inputBufferReady;\n>         Signal<FrameBuffer *> outputBufferReady;\n> diff --git a/include/libcamera/internal/converter/converter_v4l2_m2m.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h\n> index 0da62290..58fd19db 100644\n> --- a/include/libcamera/internal/converter/converter_v4l2_m2m.h\n> +++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h\n> @@ -28,6 +28,7 @@ class FrameBuffer;\n>  class MediaDevice;\n>  class Size;\n>  class SizeRange;\n> +class Stream;\n>  struct StreamConfiguration;\n>  class V4L2M2MDevice;\n>  \n> @@ -47,20 +48,20 @@ public:\n>  \n>         int configure(const StreamConfiguration &inputCfg,\n>                       const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfg);\n> -       int exportBuffers(unsigned int output, unsigned int count,\n> +       int exportBuffers(const Stream *stream, unsigned int count,\n>                           std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n>  \n>         int start();\n>         void stop();\n>  \n>         int queueBuffers(FrameBuffer *input,\n> -                        const std::map<unsigned int, FrameBuffer *> &outputs);\n> +                        const std::map<const Stream *, FrameBuffer *> &outputs);\n>  \n>  private:\n>         class V4L2M2MStream : protected Loggable\n>         {\n>         public:\n> -               V4L2M2MStream(V4L2M2MConverter *converter, unsigned int index);\n> +               V4L2M2MStream(V4L2M2MConverter *converter, const Stream *stream);\n>  \n>                 bool isValid() const { return m2m_ != nullptr; }\n>  \n> @@ -82,7 +83,7 @@ private:\n>                 void outputBufferReady(FrameBuffer *buffer);\n>  \n>                 V4L2M2MConverter *converter_;\n> -               unsigned int index_;\n> +               const Stream *stream_;\n>                 std::unique_ptr<V4L2M2MDevice> m2m_;\n>  \n>                 unsigned int inputBufferCount_;\n> @@ -91,7 +92,7 @@ private:\n>  \n>         std::unique_ptr<V4L2M2MDevice> m2m_;\n>  \n> -       std::vector<V4L2M2MStream> streams_;\n> +       std::map<const Stream *, V4L2M2MStream> streams_;\n>         std::map<FrameBuffer *, unsigned int> queue_;\n>  };\n>  \n> diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h\n> index 7e9fae6a..09cc0f6f 100644\n> --- a/include/libcamera/internal/software_isp/software_isp.h\n> +++ b/include/libcamera/internal/software_isp/software_isp.h\n> @@ -37,6 +37,7 @@ namespace libcamera {\n>  class DebayerCpu;\n>  class FrameBuffer;\n>  class PixelFormat;\n> +class Stream;\n>  struct StreamConfiguration;\n>  \n>  LOG_DECLARE_CATEGORY(SoftwareIsp)\n> @@ -62,7 +63,7 @@ public:\n>                       const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,\n>                       const ControlInfoMap &sensorControls);\n>  \n> -       int exportBuffers(unsigned int output, unsigned int count,\n> +       int exportBuffers(const Stream *stream, unsigned int count,\n>                           std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n>  \n>         void processStats(const ControlList &sensorControls);\n> @@ -71,7 +72,7 @@ public:\n>         void stop();\n>  \n>         int queueBuffers(FrameBuffer *input,\n> -                        const std::map<unsigned int, FrameBuffer *> &outputs);\n> +                        const std::map<const Stream *, FrameBuffer *> &outputs);\n>  \n>         void process(FrameBuffer *input, FrameBuffer *output);\n>  \n> diff --git a/src/libcamera/converter/converter_v4l2_m2m.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp\n> index 6309a0c0..a48b2a87 100644\n> --- a/src/libcamera/converter/converter_v4l2_m2m.cpp\n> +++ b/src/libcamera/converter/converter_v4l2_m2m.cpp\n> @@ -35,8 +35,8 @@ LOG_DECLARE_CATEGORY(Converter)\n>   * V4L2M2MConverter::V4L2M2MStream\n>   */\n>  \n> -V4L2M2MConverter::V4L2M2MStream::V4L2M2MStream(V4L2M2MConverter *converter, unsigned int index)\n> -       : converter_(converter), index_(index)\n> +V4L2M2MConverter::V4L2M2MStream::V4L2M2MStream(V4L2M2MConverter *converter, const Stream *stream)\n> +       : converter_(converter), stream_(stream)\n>  {\n>         m2m_ = std::make_unique<V4L2M2MDevice>(converter->deviceNode());\n>  \n> @@ -157,7 +157,7 @@ int V4L2M2MConverter::V4L2M2MStream::queueBuffers(FrameBuffer *input, FrameBuffe\n>  \n>  std::string V4L2M2MConverter::V4L2M2MStream::logPrefix() const\n>  {\n> -       return \"stream\" + std::to_string(index_);\n> +       return stream_->configuration().toString();\n>  }\n>  \n>  void V4L2M2MConverter::V4L2M2MStream::outputBufferReady(FrameBuffer *buffer)\n> @@ -333,10 +333,13 @@ int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg,\n>         int ret = 0;\n>  \n>         streams_.clear();\n> -       streams_.reserve(outputCfgs.size());\n>  \n>         for (unsigned int i = 0; i < outputCfgs.size(); ++i) {\n> -               V4L2M2MStream &stream = streams_.emplace_back(this, i);\n> +               const StreamConfiguration &cfg = outputCfgs[i];\n> +               streams_.emplace(cfg.stream(),\n> +                                V4L2M2MStream(this, cfg.stream()));\n> +\n> +               V4L2M2MStream &stream = streams_.at(cfg.stream());\n>  \n>                 if (!stream.isValid()) {\n>                         LOG(Converter, Error)\n> @@ -345,7 +348,7 @@ int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg,\n>                         break;\n>                 }\n>  \n> -               ret = stream.configure(inputCfg, outputCfgs[i]);\n> +               ret = stream.configure(inputCfg, cfg);\n>                 if (ret < 0)\n>                         break;\n>         }\n> @@ -361,13 +364,14 @@ int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg,\n>  /**\n>   * \\copydoc libcamera::Converter::exportBuffers\n>   */\n> -int V4L2M2MConverter::exportBuffers(unsigned int output, unsigned int count,\n> +int V4L2M2MConverter::exportBuffers(const Stream *stream, unsigned int count,\n>                                     std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n>  {\n> -       if (output >= streams_.size())\n> +       auto iter = streams_.find(stream);\n> +       if (iter == streams_.end())\n>                 return -EINVAL;\n>  \n> -       return streams_[output].exportBuffers(count, buffers);\n> +       return iter->second.exportBuffers(count, buffers);\n>  }\n>  \n>  /**\n> @@ -377,8 +381,8 @@ int V4L2M2MConverter::start()\n>  {\n>         int ret;\n>  \n> -       for (V4L2M2MStream &stream : streams_) {\n> -               ret = stream.start();\n> +       for (auto &iter : streams_) {\n> +               ret = iter.second.start();\n>                 if (ret < 0) {\n>                         stop();\n>                         return ret;\n> @@ -393,15 +397,15 @@ int V4L2M2MConverter::start()\n>   */\n>  void V4L2M2MConverter::stop()\n>  {\n> -       for (V4L2M2MStream &stream : utils::reverse(streams_))\n> -               stream.stop();\n> +       for (auto &iter : streams_)\n> +               iter.second.stop();\n>  }\n>  \n>  /**\n>   * \\copydoc libcamera::Converter::queueBuffers\n>   */\n>  int V4L2M2MConverter::queueBuffers(FrameBuffer *input,\n> -                                  const std::map<unsigned int, FrameBuffer *> &outputs)\n> +                                  const std::map<const Stream *, FrameBuffer *> &outputs)\n>  {\n>         std::set<FrameBuffer *> outputBufs;\n>         int ret;\n> @@ -414,11 +418,9 @@ int V4L2M2MConverter::queueBuffers(FrameBuffer *input,\n>         if (outputs.empty())\n>                 return -EINVAL;\n>  \n> -       for (auto [index, buffer] : outputs) {\n> +       for (auto [stream, buffer] : outputs) {\n>                 if (!buffer)\n>                         return -EINVAL;\n> -               if (index >= streams_.size())\n> -                       return -EINVAL;\n>  \n>                 outputBufs.insert(buffer);\n>         }\n> @@ -427,8 +429,8 @@ int V4L2M2MConverter::queueBuffers(FrameBuffer *input,\n>                 return -EINVAL;\n>  \n>         /* Queue the input and output buffers to all the streams. */\n> -       for (auto [index, buffer] : outputs) {\n> -               ret = streams_[index].queueBuffers(input, buffer);\n> +       for (auto [stream, buffer] : outputs) {\n> +               ret = streams_.at(stream).queueBuffers(input, buffer);\n>                 if (ret < 0)\n>                         return ret;\n>         }\n> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> index db3575c3..01ad91a7 100644\n> --- a/src/libcamera/pipeline/simple/simple.cpp\n> +++ b/src/libcamera/pipeline/simple/simple.cpp\n> @@ -278,7 +278,7 @@ public:\n>         std::map<PixelFormat, std::vector<const Configuration *>> formats_;\n>  \n>         std::vector<std::unique_ptr<FrameBuffer>> conversionBuffers_;\n> -       std::queue<std::map<unsigned int, FrameBuffer *>> conversionQueue_;\n> +       std::queue<std::map<const Stream *, FrameBuffer *>> conversionQueue_;\n>         bool useConversion_;\n>  \n>         std::unique_ptr<Converter> converter_;\n> @@ -837,7 +837,7 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)\n>         Request *request = buffer->request();\n>  \n>         if (useConversion_ && !conversionQueue_.empty()) {\n> -               const std::map<unsigned int, FrameBuffer *> &outputs =\n> +               const std::map<const Stream *, FrameBuffer *> &outputs =\n>                         conversionQueue_.front();\n>                 if (!outputs.empty()) {\n>                         FrameBuffer *outputBuffer = outputs.begin()->second;\n> @@ -1304,10 +1304,8 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,\n>          */\n>         if (data->useConversion_)\n>                 return data->converter_\n> -                              ? data->converter_->exportBuffers(data->streamIndex(stream),\n> -                                                                count, buffers)\n> -                              : data->swIsp_->exportBuffers(data->streamIndex(stream),\n> -                                                            count, buffers);\n> +                              ? data->converter_->exportBuffers(stream, count, buffers)\n> +                              : data->swIsp_->exportBuffers(stream, count, buffers);\n>         else\n>                 return data->video_->exportBuffers(count, buffers);\n>  }\n> @@ -1399,7 +1397,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)\n>         SimpleCameraData *data = cameraData(camera);\n>         int ret;\n>  \n> -       std::map<unsigned int, FrameBuffer *> buffers;\n> +       std::map<const Stream *, FrameBuffer *> buffers;\n>  \n>         for (auto &[stream, buffer] : request->buffers()) {\n>                 /*\n> @@ -1408,7 +1406,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)\n>                  * completion handler.\n>                  */\n>                 if (data->useConversion_) {\n> -                       buffers.emplace(data->streamIndex(stream), buffer);\n> +                       buffers.emplace(stream, buffer);\n>                 } else {\n>                         ret = data->video_->queueBuffer(buffer);\n>                         if (ret < 0)\n> diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\n> index ac10d82d..7cadd585 100644\n> --- a/src/libcamera/software_isp/software_isp.cpp\n> +++ b/src/libcamera/software_isp/software_isp.cpp\n> @@ -227,13 +227,13 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg,\n>   * \\return The number of allocated buffers on success or a negative error code\n>   * otherwise\n>   */\n> -int SoftwareIsp::exportBuffers(unsigned int output, unsigned int count,\n> +int SoftwareIsp::exportBuffers(const Stream *stream, unsigned int count,\n>                                std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n>  {\n>         ASSERT(debayer_ != nullptr);\n>  \n>         /* single output for now */\n> -       if (output >= 1)\n> +       if (stream == nullptr)\n>                 return -EINVAL;\n>  \n>         for (unsigned int i = 0; i < count; i++) {\n> @@ -265,7 +265,7 @@ int SoftwareIsp::exportBuffers(unsigned int output, unsigned int count,\n>   * \\return 0 on success, a negative errno on failure\n>   */\n>  int SoftwareIsp::queueBuffers(FrameBuffer *input,\n> -                             const std::map<unsigned int, FrameBuffer *> &outputs)\n> +                             const std::map<const Stream *, FrameBuffer *> &outputs)\n>  {\n>         /*\n>          * Validate the outputs as a sanity check: at least one output is\n> @@ -274,14 +274,15 @@ int SoftwareIsp::queueBuffers(FrameBuffer *input,\n>         if (outputs.empty())\n>                 return -EINVAL;\n>  \n> -       for (auto [index, buffer] : outputs) {\n> +       for (auto [stream, buffer] : outputs) {\n>                 if (!buffer)\n>                         return -EINVAL;\n> -               if (index >= 1) /* only single stream atm */\n> +               if (outputs.size() >= 1) /* only single stream atm */\n>                         return -EINVAL;\n>         }\n>  \n> -       process(input, outputs.at(0));\n> +       for (auto iter = outputs.begin(); iter != outputs.end(); iter++)\n> +               process(input, iter->second);\n>  \n>         return 0;\n>  }\n> -- \n> 2.44.0\n>","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 AA7BDBD87C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 29 May 2024 10:00:21 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E9483634AF;\n\tWed, 29 May 2024 12:00:20 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 740FC6347E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 May 2024 12:00:19 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 9FC589CA;\n\tWed, 29 May 2024 12:00:15 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"XXFEkVeU\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1716976815;\n\tbh=g7mXKnwwkYCiTBJ3XX3J827rwYElp7qL+S5a5qSYoSo=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=XXFEkVeUqAQgSLnru356fdDzjQDk6E5UvGg8x1jghOKI4X2oFoyU/EbwUf9iF1n2S\n\t8nc/AB0BFFRcMEfpmLxv1+TjKMjqqkANtb+0Ma+fcWsjDJdJNwIh1rYQNOpLEZoyV8\n\tsLooyYDpHX38mQSsapoze2sr9RqB9KrK4kxWqHQw=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20240529070248.12186-5-umang.jain@ideasonboard.com>","References":"<20240529070248.12186-1-umang.jain@ideasonboard.com>\n\t<20240529070248.12186-5-umang.jain@ideasonboard.com>","Subject":"Re: [PATCH v2 4/4] libcamera: converter: Replace usage of stream\n\tindex by Stream pointer","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Milan Zamazal <mzamazal@redhat.com>,\n\tAndrey Konovalov <andrey.konovalov@linaro.org>,\n\tUmang Jain <umang.jain@ideasonboard.com>","To":"Umang Jain <umang.jain@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Wed, 29 May 2024 11:00:15 +0100","Message-ID":"<171697681598.2248009.3497432656697474058@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":29655,"web_url":"https://patchwork.libcamera.org/comment/29655/","msgid":"<171698094642.2248009.2079078277989763550@ping.linuxembedded.co.uk>","date":"2024-05-29T11:09:06","subject":"Re: [PATCH v2 4/4] libcamera: converter: Replace usage of stream\n\tindex by Stream pointer","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Kieran Bingham (2024-05-29 11:00:15)\n> Quoting Umang Jain (2024-05-29 08:02:48)\n> > The converter interface uses the unsigned int output stream index to map\n> > to the output frame buffers. This is cumbersome to implement new\n> > converters because one has to keep around additional book keeping\n> > to track the streams with their correct indexes.\n> > \n> > The v4l2_converter_m2m and simple pipeline handler are adapted to\n> > use the new interface. This work roped in software ISP as well,\n> > which also seems to use indexes (although it doesn't implement converter\n> > interface) because of a common conversionQueue_ queue used for\n> > converter_ and swIsp_.\n> \n> Unfortunately - this patch breaks the SoftISP on Lenovo-X13s presently.\n> \n> I haven't looked into why yet, just that it breaks the camera.\n> \n\nThe CI also picked up that the Doxygen names need cleanup in here:\n\n - https://gitlab.freedesktop.org/camera/libcamera/-/jobs/59287644\n\nFAILED: Documentation/api-html\n/usr/bin/doxygen Documentation/Doxyfile\n/builds/camera/libcamera/src/libcamera/converter.cpp:113: error: argument 'output' of command @param is not found in the argument list of libcamera::Converter::exportBuffers(const Stream *stream, unsigned int count, std::vector< std::unique_ptr< FrameBuffer > > *buffers)=0 (warning treated as error, aborting now)\n\n--\nRegards\n\nKieran\n\n> > Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n> > ---\n> >  include/libcamera/internal/converter.h        |  5 ++-\n> >  .../internal/converter/converter_v4l2_m2m.h   | 11 ++---\n> >  .../internal/software_isp/software_isp.h      |  5 ++-\n> >  .../converter/converter_v4l2_m2m.cpp          | 40 ++++++++++---------\n> >  src/libcamera/pipeline/simple/simple.cpp      | 14 +++----\n> >  src/libcamera/software_isp/software_isp.cpp   | 13 +++---\n> >  6 files changed, 46 insertions(+), 42 deletions(-)\n> > \n> > diff --git a/include/libcamera/internal/converter.h b/include/libcamera/internal/converter.h\n> > index 5d74db6b..b51563d7 100644\n> > --- a/include/libcamera/internal/converter.h\n> > +++ b/include/libcamera/internal/converter.h\n> > @@ -26,6 +26,7 @@ namespace libcamera {\n> >  class FrameBuffer;\n> >  class MediaDevice;\n> >  class PixelFormat;\n> > +class Stream;\n> >  struct StreamConfiguration;\n> >  \n> >  class Converter\n> > @@ -46,14 +47,14 @@ public:\n> >  \n> >         virtual int configure(const StreamConfiguration &inputCfg,\n> >                               const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs) = 0;\n> > -       virtual int exportBuffers(unsigned int output, unsigned int count,\n> > +       virtual int exportBuffers(const Stream *stream, unsigned int count,\n> >                                   std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;\n> >  \n> >         virtual int start() = 0;\n> >         virtual void stop() = 0;\n> >  \n> >         virtual int queueBuffers(FrameBuffer *input,\n> > -                                const std::map<unsigned int, FrameBuffer *> &outputs) = 0;\n> > +                                const std::map<const Stream *, FrameBuffer *> &outputs) = 0;\n> >  \n> >         Signal<FrameBuffer *> inputBufferReady;\n> >         Signal<FrameBuffer *> outputBufferReady;\n> > diff --git a/include/libcamera/internal/converter/converter_v4l2_m2m.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h\n> > index 0da62290..58fd19db 100644\n> > --- a/include/libcamera/internal/converter/converter_v4l2_m2m.h\n> > +++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h\n> > @@ -28,6 +28,7 @@ class FrameBuffer;\n> >  class MediaDevice;\n> >  class Size;\n> >  class SizeRange;\n> > +class Stream;\n> >  struct StreamConfiguration;\n> >  class V4L2M2MDevice;\n> >  \n> > @@ -47,20 +48,20 @@ public:\n> >  \n> >         int configure(const StreamConfiguration &inputCfg,\n> >                       const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfg);\n> > -       int exportBuffers(unsigned int output, unsigned int count,\n> > +       int exportBuffers(const Stream *stream, unsigned int count,\n> >                           std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n> >  \n> >         int start();\n> >         void stop();\n> >  \n> >         int queueBuffers(FrameBuffer *input,\n> > -                        const std::map<unsigned int, FrameBuffer *> &outputs);\n> > +                        const std::map<const Stream *, FrameBuffer *> &outputs);\n> >  \n> >  private:\n> >         class V4L2M2MStream : protected Loggable\n> >         {\n> >         public:\n> > -               V4L2M2MStream(V4L2M2MConverter *converter, unsigned int index);\n> > +               V4L2M2MStream(V4L2M2MConverter *converter, const Stream *stream);\n> >  \n> >                 bool isValid() const { return m2m_ != nullptr; }\n> >  \n> > @@ -82,7 +83,7 @@ private:\n> >                 void outputBufferReady(FrameBuffer *buffer);\n> >  \n> >                 V4L2M2MConverter *converter_;\n> > -               unsigned int index_;\n> > +               const Stream *stream_;\n> >                 std::unique_ptr<V4L2M2MDevice> m2m_;\n> >  \n> >                 unsigned int inputBufferCount_;\n> > @@ -91,7 +92,7 @@ private:\n> >  \n> >         std::unique_ptr<V4L2M2MDevice> m2m_;\n> >  \n> > -       std::vector<V4L2M2MStream> streams_;\n> > +       std::map<const Stream *, V4L2M2MStream> streams_;\n> >         std::map<FrameBuffer *, unsigned int> queue_;\n> >  };\n> >  \n> > diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h\n> > index 7e9fae6a..09cc0f6f 100644\n> > --- a/include/libcamera/internal/software_isp/software_isp.h\n> > +++ b/include/libcamera/internal/software_isp/software_isp.h\n> > @@ -37,6 +37,7 @@ namespace libcamera {\n> >  class DebayerCpu;\n> >  class FrameBuffer;\n> >  class PixelFormat;\n> > +class Stream;\n> >  struct StreamConfiguration;\n> >  \n> >  LOG_DECLARE_CATEGORY(SoftwareIsp)\n> > @@ -62,7 +63,7 @@ public:\n> >                       const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,\n> >                       const ControlInfoMap &sensorControls);\n> >  \n> > -       int exportBuffers(unsigned int output, unsigned int count,\n> > +       int exportBuffers(const Stream *stream, unsigned int count,\n> >                           std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n> >  \n> >         void processStats(const ControlList &sensorControls);\n> > @@ -71,7 +72,7 @@ public:\n> >         void stop();\n> >  \n> >         int queueBuffers(FrameBuffer *input,\n> > -                        const std::map<unsigned int, FrameBuffer *> &outputs);\n> > +                        const std::map<const Stream *, FrameBuffer *> &outputs);\n> >  \n> >         void process(FrameBuffer *input, FrameBuffer *output);\n> >  \n> > diff --git a/src/libcamera/converter/converter_v4l2_m2m.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp\n> > index 6309a0c0..a48b2a87 100644\n> > --- a/src/libcamera/converter/converter_v4l2_m2m.cpp\n> > +++ b/src/libcamera/converter/converter_v4l2_m2m.cpp\n> > @@ -35,8 +35,8 @@ LOG_DECLARE_CATEGORY(Converter)\n> >   * V4L2M2MConverter::V4L2M2MStream\n> >   */\n> >  \n> > -V4L2M2MConverter::V4L2M2MStream::V4L2M2MStream(V4L2M2MConverter *converter, unsigned int index)\n> > -       : converter_(converter), index_(index)\n> > +V4L2M2MConverter::V4L2M2MStream::V4L2M2MStream(V4L2M2MConverter *converter, const Stream *stream)\n> > +       : converter_(converter), stream_(stream)\n> >  {\n> >         m2m_ = std::make_unique<V4L2M2MDevice>(converter->deviceNode());\n> >  \n> > @@ -157,7 +157,7 @@ int V4L2M2MConverter::V4L2M2MStream::queueBuffers(FrameBuffer *input, FrameBuffe\n> >  \n> >  std::string V4L2M2MConverter::V4L2M2MStream::logPrefix() const\n> >  {\n> > -       return \"stream\" + std::to_string(index_);\n> > +       return stream_->configuration().toString();\n> >  }\n> >  \n> >  void V4L2M2MConverter::V4L2M2MStream::outputBufferReady(FrameBuffer *buffer)\n> > @@ -333,10 +333,13 @@ int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg,\n> >         int ret = 0;\n> >  \n> >         streams_.clear();\n> > -       streams_.reserve(outputCfgs.size());\n> >  \n> >         for (unsigned int i = 0; i < outputCfgs.size(); ++i) {\n> > -               V4L2M2MStream &stream = streams_.emplace_back(this, i);\n> > +               const StreamConfiguration &cfg = outputCfgs[i];\n> > +               streams_.emplace(cfg.stream(),\n> > +                                V4L2M2MStream(this, cfg.stream()));\n> > +\n> > +               V4L2M2MStream &stream = streams_.at(cfg.stream());\n> >  \n> >                 if (!stream.isValid()) {\n> >                         LOG(Converter, Error)\n> > @@ -345,7 +348,7 @@ int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg,\n> >                         break;\n> >                 }\n> >  \n> > -               ret = stream.configure(inputCfg, outputCfgs[i]);\n> > +               ret = stream.configure(inputCfg, cfg);\n> >                 if (ret < 0)\n> >                         break;\n> >         }\n> > @@ -361,13 +364,14 @@ int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg,\n> >  /**\n> >   * \\copydoc libcamera::Converter::exportBuffers\n> >   */\n> > -int V4L2M2MConverter::exportBuffers(unsigned int output, unsigned int count,\n> > +int V4L2M2MConverter::exportBuffers(const Stream *stream, unsigned int count,\n> >                                     std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n> >  {\n> > -       if (output >= streams_.size())\n> > +       auto iter = streams_.find(stream);\n> > +       if (iter == streams_.end())\n> >                 return -EINVAL;\n> >  \n> > -       return streams_[output].exportBuffers(count, buffers);\n> > +       return iter->second.exportBuffers(count, buffers);\n> >  }\n> >  \n> >  /**\n> > @@ -377,8 +381,8 @@ int V4L2M2MConverter::start()\n> >  {\n> >         int ret;\n> >  \n> > -       for (V4L2M2MStream &stream : streams_) {\n> > -               ret = stream.start();\n> > +       for (auto &iter : streams_) {\n> > +               ret = iter.second.start();\n> >                 if (ret < 0) {\n> >                         stop();\n> >                         return ret;\n> > @@ -393,15 +397,15 @@ int V4L2M2MConverter::start()\n> >   */\n> >  void V4L2M2MConverter::stop()\n> >  {\n> > -       for (V4L2M2MStream &stream : utils::reverse(streams_))\n> > -               stream.stop();\n> > +       for (auto &iter : streams_)\n> > +               iter.second.stop();\n> >  }\n> >  \n> >  /**\n> >   * \\copydoc libcamera::Converter::queueBuffers\n> >   */\n> >  int V4L2M2MConverter::queueBuffers(FrameBuffer *input,\n> > -                                  const std::map<unsigned int, FrameBuffer *> &outputs)\n> > +                                  const std::map<const Stream *, FrameBuffer *> &outputs)\n> >  {\n> >         std::set<FrameBuffer *> outputBufs;\n> >         int ret;\n> > @@ -414,11 +418,9 @@ int V4L2M2MConverter::queueBuffers(FrameBuffer *input,\n> >         if (outputs.empty())\n> >                 return -EINVAL;\n> >  \n> > -       for (auto [index, buffer] : outputs) {\n> > +       for (auto [stream, buffer] : outputs) {\n> >                 if (!buffer)\n> >                         return -EINVAL;\n> > -               if (index >= streams_.size())\n> > -                       return -EINVAL;\n> >  \n> >                 outputBufs.insert(buffer);\n> >         }\n> > @@ -427,8 +429,8 @@ int V4L2M2MConverter::queueBuffers(FrameBuffer *input,\n> >                 return -EINVAL;\n> >  \n> >         /* Queue the input and output buffers to all the streams. */\n> > -       for (auto [index, buffer] : outputs) {\n> > -               ret = streams_[index].queueBuffers(input, buffer);\n> > +       for (auto [stream, buffer] : outputs) {\n> > +               ret = streams_.at(stream).queueBuffers(input, buffer);\n> >                 if (ret < 0)\n> >                         return ret;\n> >         }\n> > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> > index db3575c3..01ad91a7 100644\n> > --- a/src/libcamera/pipeline/simple/simple.cpp\n> > +++ b/src/libcamera/pipeline/simple/simple.cpp\n> > @@ -278,7 +278,7 @@ public:\n> >         std::map<PixelFormat, std::vector<const Configuration *>> formats_;\n> >  \n> >         std::vector<std::unique_ptr<FrameBuffer>> conversionBuffers_;\n> > -       std::queue<std::map<unsigned int, FrameBuffer *>> conversionQueue_;\n> > +       std::queue<std::map<const Stream *, FrameBuffer *>> conversionQueue_;\n> >         bool useConversion_;\n> >  \n> >         std::unique_ptr<Converter> converter_;\n> > @@ -837,7 +837,7 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)\n> >         Request *request = buffer->request();\n> >  \n> >         if (useConversion_ && !conversionQueue_.empty()) {\n> > -               const std::map<unsigned int, FrameBuffer *> &outputs =\n> > +               const std::map<const Stream *, FrameBuffer *> &outputs =\n> >                         conversionQueue_.front();\n> >                 if (!outputs.empty()) {\n> >                         FrameBuffer *outputBuffer = outputs.begin()->second;\n> > @@ -1304,10 +1304,8 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,\n> >          */\n> >         if (data->useConversion_)\n> >                 return data->converter_\n> > -                              ? data->converter_->exportBuffers(data->streamIndex(stream),\n> > -                                                                count, buffers)\n> > -                              : data->swIsp_->exportBuffers(data->streamIndex(stream),\n> > -                                                            count, buffers);\n> > +                              ? data->converter_->exportBuffers(stream, count, buffers)\n> > +                              : data->swIsp_->exportBuffers(stream, count, buffers);\n> >         else\n> >                 return data->video_->exportBuffers(count, buffers);\n> >  }\n> > @@ -1399,7 +1397,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)\n> >         SimpleCameraData *data = cameraData(camera);\n> >         int ret;\n> >  \n> > -       std::map<unsigned int, FrameBuffer *> buffers;\n> > +       std::map<const Stream *, FrameBuffer *> buffers;\n> >  \n> >         for (auto &[stream, buffer] : request->buffers()) {\n> >                 /*\n> > @@ -1408,7 +1406,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)\n> >                  * completion handler.\n> >                  */\n> >                 if (data->useConversion_) {\n> > -                       buffers.emplace(data->streamIndex(stream), buffer);\n> > +                       buffers.emplace(stream, buffer);\n> >                 } else {\n> >                         ret = data->video_->queueBuffer(buffer);\n> >                         if (ret < 0)\n> > diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\n> > index ac10d82d..7cadd585 100644\n> > --- a/src/libcamera/software_isp/software_isp.cpp\n> > +++ b/src/libcamera/software_isp/software_isp.cpp\n> > @@ -227,13 +227,13 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg,\n> >   * \\return The number of allocated buffers on success or a negative error code\n> >   * otherwise\n> >   */\n> > -int SoftwareIsp::exportBuffers(unsigned int output, unsigned int count,\n> > +int SoftwareIsp::exportBuffers(const Stream *stream, unsigned int count,\n> >                                std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n> >  {\n> >         ASSERT(debayer_ != nullptr);\n> >  \n> >         /* single output for now */\n> > -       if (output >= 1)\n> > +       if (stream == nullptr)\n> >                 return -EINVAL;\n> >  \n> >         for (unsigned int i = 0; i < count; i++) {\n> > @@ -265,7 +265,7 @@ int SoftwareIsp::exportBuffers(unsigned int output, unsigned int count,\n> >   * \\return 0 on success, a negative errno on failure\n> >   */\n> >  int SoftwareIsp::queueBuffers(FrameBuffer *input,\n> > -                             const std::map<unsigned int, FrameBuffer *> &outputs)\n> > +                             const std::map<const Stream *, FrameBuffer *> &outputs)\n> >  {\n> >         /*\n> >          * Validate the outputs as a sanity check: at least one output is\n> > @@ -274,14 +274,15 @@ int SoftwareIsp::queueBuffers(FrameBuffer *input,\n> >         if (outputs.empty())\n> >                 return -EINVAL;\n> >  \n> > -       for (auto [index, buffer] : outputs) {\n> > +       for (auto [stream, buffer] : outputs) {\n> >                 if (!buffer)\n> >                         return -EINVAL;\n> > -               if (index >= 1) /* only single stream atm */\n> > +               if (outputs.size() >= 1) /* only single stream atm */\n> >                         return -EINVAL;\n> >         }\n> >  \n> > -       process(input, outputs.at(0));\n> > +       for (auto iter = outputs.begin(); iter != outputs.end(); iter++)\n> > +               process(input, iter->second);\n> >  \n> >         return 0;\n> >  }\n> > -- \n> > 2.44.0\n> >","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 0D15EBDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 29 May 2024 11:09:11 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 8224B634BA;\n\tWed, 29 May 2024 13:09:10 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 43268634AF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 May 2024 13:09:09 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id CBABE4CD;\n\tWed, 29 May 2024 13:09:05 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"YjKQ0sl3\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1716980945;\n\tbh=pr3k6OA66GVXdDih23bvLqK6/poYazdEagWFUBaGihY=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=YjKQ0sl3ye5woRlRfYkfPCvdmH69U7U0889t0C9ytLBoiBIBccmy32eUAbU6zdxwK\n\tJzg4RIxkKR86hs9kR1KIlWjAhmsERpqzvGu5MiJAbZriFKvIf57j3XeISolYlaz1Q+\n\t1sYewXiCtIyMpbOUGRYc/SSis0dOKsNKTj6SQPrM=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<171697681598.2248009.3497432656697474058@ping.linuxembedded.co.uk>","References":"<20240529070248.12186-1-umang.jain@ideasonboard.com>\n\t<20240529070248.12186-5-umang.jain@ideasonboard.com>\n\t<171697681598.2248009.3497432656697474058@ping.linuxembedded.co.uk>","Subject":"Re: [PATCH v2 4/4] libcamera: converter: Replace usage of stream\n\tindex by Stream pointer","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Milan Zamazal <mzamazal@redhat.com>,\n\tAndrey Konovalov <andrey.konovalov@linaro.org>,\n\tUmang Jain <umang.jain@ideasonboard.com>","To":"Umang Jain <umang.jain@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Wed, 29 May 2024 12:09:06 +0100","Message-ID":"<171698094642.2248009.2079078277989763550@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":29656,"web_url":"https://patchwork.libcamera.org/comment/29656/","msgid":"<185247fc-6202-474b-9ffb-b1f28ce14019@ideasonboard.com>","date":"2024-05-29T11:10:49","subject":"Re: [PATCH v2 4/4] libcamera: converter: Replace usage of stream\n\tindex by Stream pointer","submitter":{"id":86,"url":"https://patchwork.libcamera.org/api/people/86/","name":"Umang Jain","email":"umang.jain@ideasonboard.com"},"content":"Hi Kieran,\n\nOn 29/05/24 3:30 pm, Kieran Bingham wrote:\n> Quoting Umang Jain (2024-05-29 08:02:48)\n>> The converter interface uses the unsigned int output stream index to map\n>> to the output frame buffers. This is cumbersome to implement new\n>> converters because one has to keep around additional book keeping\n>> to track the streams with their correct indexes.\n>>\n>> The v4l2_converter_m2m and simple pipeline handler are adapted to\n>> use the new interface. This work roped in software ISP as well,\n>> which also seems to use indexes (although it doesn't implement converter\n>> interface) because of a common conversionQueue_ queue used for\n>> converter_ and swIsp_.\n> Unfortunately - this patch breaks the SoftISP on Lenovo-X13s presently.\n\nah darn...\n\nThanks for testing! I am setting up software ISP pipeline on my side. I \nwill investigate.\n>\n> I haven't looked into why yet, just that it breaks the camera.\n>\n> --\n> Kieran\n>\n>\n>> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n>> ---\n>>   include/libcamera/internal/converter.h        |  5 ++-\n>>   .../internal/converter/converter_v4l2_m2m.h   | 11 ++---\n>>   .../internal/software_isp/software_isp.h      |  5 ++-\n>>   .../converter/converter_v4l2_m2m.cpp          | 40 ++++++++++---------\n>>   src/libcamera/pipeline/simple/simple.cpp      | 14 +++----\n>>   src/libcamera/software_isp/software_isp.cpp   | 13 +++---\n>>   6 files changed, 46 insertions(+), 42 deletions(-)\n>>\n>> diff --git a/include/libcamera/internal/converter.h b/include/libcamera/internal/converter.h\n>> index 5d74db6b..b51563d7 100644\n>> --- a/include/libcamera/internal/converter.h\n>> +++ b/include/libcamera/internal/converter.h\n>> @@ -26,6 +26,7 @@ namespace libcamera {\n>>   class FrameBuffer;\n>>   class MediaDevice;\n>>   class PixelFormat;\n>> +class Stream;\n>>   struct StreamConfiguration;\n>>   \n>>   class Converter\n>> @@ -46,14 +47,14 @@ public:\n>>   \n>>          virtual int configure(const StreamConfiguration &inputCfg,\n>>                                const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs) = 0;\n>> -       virtual int exportBuffers(unsigned int output, unsigned int count,\n>> +       virtual int exportBuffers(const Stream *stream, unsigned int count,\n>>                                    std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;\n>>   \n>>          virtual int start() = 0;\n>>          virtual void stop() = 0;\n>>   \n>>          virtual int queueBuffers(FrameBuffer *input,\n>> -                                const std::map<unsigned int, FrameBuffer *> &outputs) = 0;\n>> +                                const std::map<const Stream *, FrameBuffer *> &outputs) = 0;\n>>   \n>>          Signal<FrameBuffer *> inputBufferReady;\n>>          Signal<FrameBuffer *> outputBufferReady;\n>> diff --git a/include/libcamera/internal/converter/converter_v4l2_m2m.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h\n>> index 0da62290..58fd19db 100644\n>> --- a/include/libcamera/internal/converter/converter_v4l2_m2m.h\n>> +++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h\n>> @@ -28,6 +28,7 @@ class FrameBuffer;\n>>   class MediaDevice;\n>>   class Size;\n>>   class SizeRange;\n>> +class Stream;\n>>   struct StreamConfiguration;\n>>   class V4L2M2MDevice;\n>>   \n>> @@ -47,20 +48,20 @@ public:\n>>   \n>>          int configure(const StreamConfiguration &inputCfg,\n>>                        const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfg);\n>> -       int exportBuffers(unsigned int output, unsigned int count,\n>> +       int exportBuffers(const Stream *stream, unsigned int count,\n>>                            std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n>>   \n>>          int start();\n>>          void stop();\n>>   \n>>          int queueBuffers(FrameBuffer *input,\n>> -                        const std::map<unsigned int, FrameBuffer *> &outputs);\n>> +                        const std::map<const Stream *, FrameBuffer *> &outputs);\n>>   \n>>   private:\n>>          class V4L2M2MStream : protected Loggable\n>>          {\n>>          public:\n>> -               V4L2M2MStream(V4L2M2MConverter *converter, unsigned int index);\n>> +               V4L2M2MStream(V4L2M2MConverter *converter, const Stream *stream);\n>>   \n>>                  bool isValid() const { return m2m_ != nullptr; }\n>>   \n>> @@ -82,7 +83,7 @@ private:\n>>                  void outputBufferReady(FrameBuffer *buffer);\n>>   \n>>                  V4L2M2MConverter *converter_;\n>> -               unsigned int index_;\n>> +               const Stream *stream_;\n>>                  std::unique_ptr<V4L2M2MDevice> m2m_;\n>>   \n>>                  unsigned int inputBufferCount_;\n>> @@ -91,7 +92,7 @@ private:\n>>   \n>>          std::unique_ptr<V4L2M2MDevice> m2m_;\n>>   \n>> -       std::vector<V4L2M2MStream> streams_;\n>> +       std::map<const Stream *, V4L2M2MStream> streams_;\n>>          std::map<FrameBuffer *, unsigned int> queue_;\n>>   };\n>>   \n>> diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h\n>> index 7e9fae6a..09cc0f6f 100644\n>> --- a/include/libcamera/internal/software_isp/software_isp.h\n>> +++ b/include/libcamera/internal/software_isp/software_isp.h\n>> @@ -37,6 +37,7 @@ namespace libcamera {\n>>   class DebayerCpu;\n>>   class FrameBuffer;\n>>   class PixelFormat;\n>> +class Stream;\n>>   struct StreamConfiguration;\n>>   \n>>   LOG_DECLARE_CATEGORY(SoftwareIsp)\n>> @@ -62,7 +63,7 @@ public:\n>>                        const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,\n>>                        const ControlInfoMap &sensorControls);\n>>   \n>> -       int exportBuffers(unsigned int output, unsigned int count,\n>> +       int exportBuffers(const Stream *stream, unsigned int count,\n>>                            std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n>>   \n>>          void processStats(const ControlList &sensorControls);\n>> @@ -71,7 +72,7 @@ public:\n>>          void stop();\n>>   \n>>          int queueBuffers(FrameBuffer *input,\n>> -                        const std::map<unsigned int, FrameBuffer *> &outputs);\n>> +                        const std::map<const Stream *, FrameBuffer *> &outputs);\n>>   \n>>          void process(FrameBuffer *input, FrameBuffer *output);\n>>   \n>> diff --git a/src/libcamera/converter/converter_v4l2_m2m.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp\n>> index 6309a0c0..a48b2a87 100644\n>> --- a/src/libcamera/converter/converter_v4l2_m2m.cpp\n>> +++ b/src/libcamera/converter/converter_v4l2_m2m.cpp\n>> @@ -35,8 +35,8 @@ LOG_DECLARE_CATEGORY(Converter)\n>>    * V4L2M2MConverter::V4L2M2MStream\n>>    */\n>>   \n>> -V4L2M2MConverter::V4L2M2MStream::V4L2M2MStream(V4L2M2MConverter *converter, unsigned int index)\n>> -       : converter_(converter), index_(index)\n>> +V4L2M2MConverter::V4L2M2MStream::V4L2M2MStream(V4L2M2MConverter *converter, const Stream *stream)\n>> +       : converter_(converter), stream_(stream)\n>>   {\n>>          m2m_ = std::make_unique<V4L2M2MDevice>(converter->deviceNode());\n>>   \n>> @@ -157,7 +157,7 @@ int V4L2M2MConverter::V4L2M2MStream::queueBuffers(FrameBuffer *input, FrameBuffe\n>>   \n>>   std::string V4L2M2MConverter::V4L2M2MStream::logPrefix() const\n>>   {\n>> -       return \"stream\" + std::to_string(index_);\n>> +       return stream_->configuration().toString();\n>>   }\n>>   \n>>   void V4L2M2MConverter::V4L2M2MStream::outputBufferReady(FrameBuffer *buffer)\n>> @@ -333,10 +333,13 @@ int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg,\n>>          int ret = 0;\n>>   \n>>          streams_.clear();\n>> -       streams_.reserve(outputCfgs.size());\n>>   \n>>          for (unsigned int i = 0; i < outputCfgs.size(); ++i) {\n>> -               V4L2M2MStream &stream = streams_.emplace_back(this, i);\n>> +               const StreamConfiguration &cfg = outputCfgs[i];\n>> +               streams_.emplace(cfg.stream(),\n>> +                                V4L2M2MStream(this, cfg.stream()));\n>> +\n>> +               V4L2M2MStream &stream = streams_.at(cfg.stream());\n>>   \n>>                  if (!stream.isValid()) {\n>>                          LOG(Converter, Error)\n>> @@ -345,7 +348,7 @@ int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg,\n>>                          break;\n>>                  }\n>>   \n>> -               ret = stream.configure(inputCfg, outputCfgs[i]);\n>> +               ret = stream.configure(inputCfg, cfg);\n>>                  if (ret < 0)\n>>                          break;\n>>          }\n>> @@ -361,13 +364,14 @@ int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg,\n>>   /**\n>>    * \\copydoc libcamera::Converter::exportBuffers\n>>    */\n>> -int V4L2M2MConverter::exportBuffers(unsigned int output, unsigned int count,\n>> +int V4L2M2MConverter::exportBuffers(const Stream *stream, unsigned int count,\n>>                                      std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n>>   {\n>> -       if (output >= streams_.size())\n>> +       auto iter = streams_.find(stream);\n>> +       if (iter == streams_.end())\n>>                  return -EINVAL;\n>>   \n>> -       return streams_[output].exportBuffers(count, buffers);\n>> +       return iter->second.exportBuffers(count, buffers);\n>>   }\n>>   \n>>   /**\n>> @@ -377,8 +381,8 @@ int V4L2M2MConverter::start()\n>>   {\n>>          int ret;\n>>   \n>> -       for (V4L2M2MStream &stream : streams_) {\n>> -               ret = stream.start();\n>> +       for (auto &iter : streams_) {\n>> +               ret = iter.second.start();\n>>                  if (ret < 0) {\n>>                          stop();\n>>                          return ret;\n>> @@ -393,15 +397,15 @@ int V4L2M2MConverter::start()\n>>    */\n>>   void V4L2M2MConverter::stop()\n>>   {\n>> -       for (V4L2M2MStream &stream : utils::reverse(streams_))\n>> -               stream.stop();\n>> +       for (auto &iter : streams_)\n>> +               iter.second.stop();\n>>   }\n>>   \n>>   /**\n>>    * \\copydoc libcamera::Converter::queueBuffers\n>>    */\n>>   int V4L2M2MConverter::queueBuffers(FrameBuffer *input,\n>> -                                  const std::map<unsigned int, FrameBuffer *> &outputs)\n>> +                                  const std::map<const Stream *, FrameBuffer *> &outputs)\n>>   {\n>>          std::set<FrameBuffer *> outputBufs;\n>>          int ret;\n>> @@ -414,11 +418,9 @@ int V4L2M2MConverter::queueBuffers(FrameBuffer *input,\n>>          if (outputs.empty())\n>>                  return -EINVAL;\n>>   \n>> -       for (auto [index, buffer] : outputs) {\n>> +       for (auto [stream, buffer] : outputs) {\n>>                  if (!buffer)\n>>                          return -EINVAL;\n>> -               if (index >= streams_.size())\n>> -                       return -EINVAL;\n>>   \n>>                  outputBufs.insert(buffer);\n>>          }\n>> @@ -427,8 +429,8 @@ int V4L2M2MConverter::queueBuffers(FrameBuffer *input,\n>>                  return -EINVAL;\n>>   \n>>          /* Queue the input and output buffers to all the streams. */\n>> -       for (auto [index, buffer] : outputs) {\n>> -               ret = streams_[index].queueBuffers(input, buffer);\n>> +       for (auto [stream, buffer] : outputs) {\n>> +               ret = streams_.at(stream).queueBuffers(input, buffer);\n>>                  if (ret < 0)\n>>                          return ret;\n>>          }\n>> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n>> index db3575c3..01ad91a7 100644\n>> --- a/src/libcamera/pipeline/simple/simple.cpp\n>> +++ b/src/libcamera/pipeline/simple/simple.cpp\n>> @@ -278,7 +278,7 @@ public:\n>>          std::map<PixelFormat, std::vector<const Configuration *>> formats_;\n>>   \n>>          std::vector<std::unique_ptr<FrameBuffer>> conversionBuffers_;\n>> -       std::queue<std::map<unsigned int, FrameBuffer *>> conversionQueue_;\n>> +       std::queue<std::map<const Stream *, FrameBuffer *>> conversionQueue_;\n>>          bool useConversion_;\n>>   \n>>          std::unique_ptr<Converter> converter_;\n>> @@ -837,7 +837,7 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)\n>>          Request *request = buffer->request();\n>>   \n>>          if (useConversion_ && !conversionQueue_.empty()) {\n>> -               const std::map<unsigned int, FrameBuffer *> &outputs =\n>> +               const std::map<const Stream *, FrameBuffer *> &outputs =\n>>                          conversionQueue_.front();\n>>                  if (!outputs.empty()) {\n>>                          FrameBuffer *outputBuffer = outputs.begin()->second;\n>> @@ -1304,10 +1304,8 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,\n>>           */\n>>          if (data->useConversion_)\n>>                  return data->converter_\n>> -                              ? data->converter_->exportBuffers(data->streamIndex(stream),\n>> -                                                                count, buffers)\n>> -                              : data->swIsp_->exportBuffers(data->streamIndex(stream),\n>> -                                                            count, buffers);\n>> +                              ? data->converter_->exportBuffers(stream, count, buffers)\n>> +                              : data->swIsp_->exportBuffers(stream, count, buffers);\n>>          else\n>>                  return data->video_->exportBuffers(count, buffers);\n>>   }\n>> @@ -1399,7 +1397,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)\n>>          SimpleCameraData *data = cameraData(camera);\n>>          int ret;\n>>   \n>> -       std::map<unsigned int, FrameBuffer *> buffers;\n>> +       std::map<const Stream *, FrameBuffer *> buffers;\n>>   \n>>          for (auto &[stream, buffer] : request->buffers()) {\n>>                  /*\n>> @@ -1408,7 +1406,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)\n>>                   * completion handler.\n>>                   */\n>>                  if (data->useConversion_) {\n>> -                       buffers.emplace(data->streamIndex(stream), buffer);\n>> +                       buffers.emplace(stream, buffer);\n>>                  } else {\n>>                          ret = data->video_->queueBuffer(buffer);\n>>                          if (ret < 0)\n>> diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\n>> index ac10d82d..7cadd585 100644\n>> --- a/src/libcamera/software_isp/software_isp.cpp\n>> +++ b/src/libcamera/software_isp/software_isp.cpp\n>> @@ -227,13 +227,13 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg,\n>>    * \\return The number of allocated buffers on success or a negative error code\n>>    * otherwise\n>>    */\n>> -int SoftwareIsp::exportBuffers(unsigned int output, unsigned int count,\n>> +int SoftwareIsp::exportBuffers(const Stream *stream, unsigned int count,\n>>                                 std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n>>   {\n>>          ASSERT(debayer_ != nullptr);\n>>   \n>>          /* single output for now */\n>> -       if (output >= 1)\n>> +       if (stream == nullptr)\n>>                  return -EINVAL;\n>>   \n>>          for (unsigned int i = 0; i < count; i++) {\n>> @@ -265,7 +265,7 @@ int SoftwareIsp::exportBuffers(unsigned int output, unsigned int count,\n>>    * \\return 0 on success, a negative errno on failure\n>>    */\n>>   int SoftwareIsp::queueBuffers(FrameBuffer *input,\n>> -                             const std::map<unsigned int, FrameBuffer *> &outputs)\n>> +                             const std::map<const Stream *, FrameBuffer *> &outputs)\n>>   {\n>>          /*\n>>           * Validate the outputs as a sanity check: at least one output is\n>> @@ -274,14 +274,15 @@ int SoftwareIsp::queueBuffers(FrameBuffer *input,\n>>          if (outputs.empty())\n>>                  return -EINVAL;\n>>   \n>> -       for (auto [index, buffer] : outputs) {\n>> +       for (auto [stream, buffer] : outputs) {\n>>                  if (!buffer)\n>>                          return -EINVAL;\n>> -               if (index >= 1) /* only single stream atm */\n>> +               if (outputs.size() >= 1) /* only single stream atm */\n>>                          return -EINVAL;\n>>          }\n>>   \n>> -       process(input, outputs.at(0));\n>> +       for (auto iter = outputs.begin(); iter != outputs.end(); iter++)\n>> +               process(input, iter->second);\n>>   \n>>          return 0;\n>>   }\n>> -- \n>> 2.44.0\n>>","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 EEBEFBDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 29 May 2024 11:10:59 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 22BFF634B9;\n\tWed, 29 May 2024 13:10:59 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E23A5634AF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 May 2024 13:10:56 +0200 (CEST)","from [192.168.81.180] (unknown [132.154.141.217])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C3FF84CD;\n\tWed, 29 May 2024 13:10:51 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"K6sjahkk\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1716981053;\n\tbh=183fL8yhZ/LYesqdr27wz7pXdOBGxJNJsAixV2bg5lQ=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=K6sjahkkXQNDns6ODMoi6kI9a/pB/IKUCuEl1yoeMvRfcBKsjJWPs2O9hMzQ05Fb3\n\t28pSguxVBqxDw5NSrmEe5eeT5ObxHaxnt7y/3XZHWdOnimnMpXG3z4dLaO1R/VEHpU\n\tkALkDfoizK6QsbcGcl69KrC/R75xPNWq3y47Xri4=","Message-ID":"<185247fc-6202-474b-9ffb-b1f28ce14019@ideasonboard.com>","Date":"Wed, 29 May 2024 16:40:49 +0530","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v2 4/4] libcamera: converter: Replace usage of stream\n\tindex by Stream pointer","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Cc":"Milan Zamazal <mzamazal@redhat.com>,\n\tAndrey Konovalov <andrey.konovalov@linaro.org>","References":"<20240529070248.12186-1-umang.jain@ideasonboard.com>\n\t<20240529070248.12186-5-umang.jain@ideasonboard.com>\n\t<171697681598.2248009.3497432656697474058@ping.linuxembedded.co.uk>","Content-Language":"en-US","From":"Umang Jain <umang.jain@ideasonboard.com>","In-Reply-To":"<171697681598.2248009.3497432656697474058@ping.linuxembedded.co.uk>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]