[{"id":26948,"web_url":"https://patchwork.libcamera.org/comment/26948/","msgid":"<t2qyw7apzkbuad5w66pyf2mobskzhuaeivgy22szgfg3rg4k54@7rl6bna7a3rr>","date":"2023-04-27T07:45:57","subject":"Re: [libcamera-devel] [PATCH] pipeline: raspberrypi: Add stream\n\tflags to RPi::Stream","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Naush\n\nOn Thu, Apr 27, 2023 at 08:24:22AM +0100, Naushir Patuck via libcamera-devel wrote:\n> Add a flags_ field to indicate stream state information in RPi::Stream.\n> This replaces the existing external_ and importOnly_ boolean flags.\n>\n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\nThanks\n   j\n\n> ---\n>  .../pipeline/rpi/common/pipeline_base.cpp     |  8 ++--\n>  .../pipeline/rpi/common/rpi_stream.cpp        | 40 ++++++++++--------\n>  .../pipeline/rpi/common/rpi_stream.h          | 42 ++++++++++++-------\n>  src/libcamera/pipeline/rpi/vc4/vc4.cpp        |  8 ++--\n>  4 files changed, 60 insertions(+), 38 deletions(-)\n>\n> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> index 012766b38c32..94ba3422ff0c 100644\n> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> @@ -31,6 +31,8 @@ using namespace RPi;\n>\n>  LOG_DEFINE_CATEGORY(RPI)\n>\n> +using StreamFlag = RPi::Stream::StreamFlag;\n> +\n>  namespace {\n>\n>  constexpr unsigned int defaultRawBitDepth = 12;\n> @@ -504,7 +506,7 @@ int PipelineHandlerBase::configure(Camera *camera, CameraConfiguration *config)\n>  \t/* Start by freeing all buffers and reset the stream states. */\n>  \tdata->freeBuffers();\n>  \tfor (auto const stream : data->streams_)\n> -\t\tstream->setExternal(false);\n> +\t\tstream->clearFlags(StreamFlag::External);\n>\n>  \tstd::vector<CameraData::StreamParams> rawStreams, ispStreams;\n>  \tstd::optional<BayerFormat::Packing> packing;\n> @@ -752,7 +754,7 @@ int PipelineHandlerBase::queueRequestDevice(Camera *camera, Request *request)\n>\n>  \t/* Push all buffers supplied in the Request to the respective streams. */\n>  \tfor (auto stream : data->streams_) {\n> -\t\tif (!stream->isExternal())\n> +\t\tif (!(stream->getFlags() & StreamFlag::External))\n>  \t\t\tcontinue;\n>\n>  \t\tFrameBuffer *buffer = request->findBuffer(stream);\n> @@ -931,7 +933,7 @@ int PipelineHandlerBase::queueAllBuffers(Camera *camera)\n>  \tint ret;\n>\n>  \tfor (auto const stream : data->streams_) {\n> -\t\tif (!stream->isExternal()) {\n> +\t\tif (!(stream->getFlags() & StreamFlag::External)) {\n>  \t\t\tret = stream->queueAllBuffers();\n>  \t\t\tif (ret < 0)\n>  \t\t\t\treturn ret;\n> diff --git a/src/libcamera/pipeline/rpi/common/rpi_stream.cpp b/src/libcamera/pipeline/rpi/common/rpi_stream.cpp\n> index b7e4130f5e56..c158843cb0ed 100644\n> --- a/src/libcamera/pipeline/rpi/common/rpi_stream.cpp\n> +++ b/src/libcamera/pipeline/rpi/common/rpi_stream.cpp\n> @@ -14,6 +14,24 @@ LOG_DEFINE_CATEGORY(RPISTREAM)\n>\n>  namespace RPi {\n>\n> +void Stream::setFlags(StreamFlags flags)\n> +{\n> +\tflags_ |= flags;\n> +\n> +\t/* Import streams cannot be external. */\n> +\tASSERT(!(flags_ & StreamFlag::External) || !(flags_ & StreamFlag::ImportOnly));\n> +}\n> +\n> +void Stream::clearFlags(StreamFlags flags)\n> +{\n> +\tflags_ &= ~flags;\n> +}\n> +\n> +RPi::Stream::StreamFlags Stream::getFlags() const\n> +{\n> +\treturn flags_;\n> +}\n> +\n>  V4L2VideoDevice *Stream::dev() const\n>  {\n>  \treturn dev_.get();\n> @@ -32,18 +50,6 @@ void Stream::resetBuffers()\n>  \t\tavailableBuffers_.push(buffer.get());\n>  }\n>\n> -void Stream::setExternal(bool external)\n> -{\n> -\t/* Import streams cannot be external. */\n> -\tASSERT(!external || !importOnly_);\n> -\texternal_ = external;\n> -}\n> -\n> -bool Stream::isExternal() const\n> -{\n> -\treturn external_;\n> -}\n> -\n>  void Stream::setExportedBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n>  {\n>  \tfor (auto const &buffer : *buffers)\n> @@ -57,7 +63,7 @@ const BufferMap &Stream::getBuffers() const\n>\n>  unsigned int Stream::getBufferId(FrameBuffer *buffer) const\n>  {\n> -\tif (importOnly_)\n> +\tif (flags_ & StreamFlag::ImportOnly)\n>  \t\treturn 0;\n>\n>  \t/* Find the buffer in the map, and return the buffer id. */\n> @@ -88,7 +94,7 @@ int Stream::prepareBuffers(unsigned int count)\n>  {\n>  \tint ret;\n>\n> -\tif (!importOnly_) {\n> +\tif (!(flags_ & StreamFlag::ImportOnly)) {\n>  \t\tif (count) {\n>  \t\t\t/* Export some frame buffers for internal use. */\n>  \t\t\tret = dev_->exportBuffers(count, &internalBuffers_);\n> @@ -113,7 +119,7 @@ int Stream::prepareBuffers(unsigned int count)\n>  \t * \\todo Find a better heuristic, or, even better, an exact solution to\n>  \t * this issue.\n>  \t */\n> -\tif (isExternal() || importOnly_)\n> +\tif ((flags_ & StreamFlag::External) || (flags_ & StreamFlag::ImportOnly))\n>  \t\tcount = count * 2;\n>\n>  \treturn dev_->importBuffers(count);\n> @@ -160,7 +166,7 @@ int Stream::queueBuffer(FrameBuffer *buffer)\n>\n>  void Stream::returnBuffer(FrameBuffer *buffer)\n>  {\n> -\tif (!external_) {\n> +\tif (!(flags_ & StreamFlag::External)) {\n>  \t\t/* For internal buffers, simply requeue back to the device. */\n>  \t\tqueueToDevice(buffer);\n>  \t\treturn;\n> @@ -204,7 +210,7 @@ int Stream::queueAllBuffers()\n>  {\n>  \tint ret;\n>\n> -\tif (external_)\n> +\tif (flags_ & StreamFlag::External)\n>  \t\treturn 0;\n>\n>  \twhile (!availableBuffers_.empty()) {\n> diff --git a/src/libcamera/pipeline/rpi/common/rpi_stream.h b/src/libcamera/pipeline/rpi/common/rpi_stream.h\n> index b8c74de35863..6edd304bdfe2 100644\n> --- a/src/libcamera/pipeline/rpi/common/rpi_stream.h\n> +++ b/src/libcamera/pipeline/rpi/common/rpi_stream.h\n> @@ -12,6 +12,7 @@\n>  #include <unordered_map>\n>  #include <vector>\n>\n> +#include <libcamera/base/flags.h>\n>  #include <libcamera/stream.h>\n>\n>  #include \"libcamera/internal/v4l2_videodevice.h\"\n> @@ -37,25 +38,41 @@ enum BufferMask {\n>  class Stream : public libcamera::Stream\n>  {\n>  public:\n> +\tenum class StreamFlag {\n> +\t\tNone\t\t= 0,\n> +\t\t/*\n> +\t\t * Indicates that this stream only imports buffers, e.g. the ISP\n> +\t\t * input stream.\n> +\t\t */\n> +\t\tImportOnly\t= (1 << 0),\n> +\t\t/*\n> +\t\t * Indicates that this stream is active externally, i.e. the\n> +\t\t * buffers might be provided by (and returned to) the application.\n> +\t\t */\n> +\t\tExternal\t= (1 << 1),\n> +\t};\n> +\n> +\tusing StreamFlags = Flags<StreamFlag>;\n> +\n>  \tStream()\n> -\t\t: id_(BufferMask::MaskID)\n> +\t\t: flags_(StreamFlag::None), id_(BufferMask::MaskID)\n>  \t{\n>  \t}\n>\n> -\tStream(const char *name, MediaEntity *dev, bool importOnly = false)\n> -\t\t: external_(false), importOnly_(importOnly), name_(name),\n> +\tStream(const char *name, MediaEntity *dev, StreamFlags flags = StreamFlag::None)\n> +\t\t: flags_(flags), name_(name),\n>  \t\t  dev_(std::make_unique<V4L2VideoDevice>(dev)), id_(BufferMask::MaskID)\n>  \t{\n>  \t}\n>\n> +\tvoid setFlags(StreamFlags flags);\n> +\tvoid clearFlags(StreamFlags flags);\n> +\tStreamFlags getFlags() const;\n> +\n>  \tV4L2VideoDevice *dev() const;\n>  \tconst std::string &name() const;\n> -\tbool isImporter() const;\n>  \tvoid resetBuffers();\n>\n> -\tvoid setExternal(bool external);\n> -\tbool isExternal() const;\n> -\n>  \tvoid setExportedBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n>  \tconst BufferMap &getBuffers() const;\n>  \tunsigned int getBufferId(FrameBuffer *buffer) const;\n> @@ -112,14 +129,7 @@ private:\n>  \tvoid clearBuffers();\n>  \tint queueToDevice(FrameBuffer *buffer);\n>\n> -\t/*\n> -\t * Indicates that this stream is active externally, i.e. the buffers\n> -\t * might be provided by (and returned to) the application.\n> -\t */\n> -\tbool external_;\n> -\n> -\t/* Indicates that this stream only imports buffers, e.g. ISP input. */\n> -\tbool importOnly_;\n> +\tStreamFlags flags_;\n>\n>  \t/* Stream name identifier. */\n>  \tstd::string name_;\n> @@ -182,4 +192,6 @@ public:\n>\n>  } /* namespace RPi */\n>\n> +LIBCAMERA_FLAGS_ENABLE_OPERATORS(RPi::Stream::StreamFlag)\n> +\n>  } /* namespace libcamera */\n> diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> index a085a06376a8..7a3445865987 100644\n> --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> @@ -23,6 +23,8 @@ namespace libcamera {\n>\n>  LOG_DECLARE_CATEGORY(RPI)\n>\n> +using StreamFlag = RPi::Stream::StreamFlag;\n> +\n>  namespace {\n>\n>  enum class Unicam : unsigned int { Image, Embedded };\n> @@ -320,7 +322,7 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer\n>  \t}\n>\n>  \t/* Tag the ISP input stream as an import stream. */\n> -\tdata->isp_[Isp::Input] = RPi::Stream(\"ISP Input\", ispOutput0, true);\n> +\tdata->isp_[Isp::Input] = RPi::Stream(\"ISP Input\", ispOutput0, StreamFlag::ImportOnly);\n>  \tdata->isp_[Isp::Output0] = RPi::Stream(\"ISP Output0\", ispCapture1);\n>  \tdata->isp_[Isp::Output1] = RPi::Stream(\"ISP Output1\", ispCapture2);\n>  \tdata->isp_[Isp::Stats] = RPi::Stream(\"ISP Stats\", ispCapture3);\n> @@ -502,7 +504,7 @@ int Vc4CameraData::platformConfigure(const V4L2SubdeviceFormat &sensorFormat,\n>  \t */\n>  \tif (!rawStreams.empty()) {\n>  \t\trawStreams[0].cfg->setStream(&unicam_[Unicam::Image]);\n> -\t\tunicam_[Unicam::Image].setExternal(true);\n> +\t\tunicam_[Unicam::Image].setFlags(StreamFlag::External);\n>  \t}\n>\n>  \tret = isp_[Isp::Input].dev()->setFormat(&unicamFormat);\n> @@ -547,7 +549,7 @@ int Vc4CameraData::platformConfigure(const V4L2SubdeviceFormat &sensorFormat,\n>  \t\t\t<< ColorSpace::toString(cfg->colorSpace);\n>\n>  \t\tcfg->setStream(stream);\n> -\t\tstream->setExternal(true);\n> +\t\tstream->setFlags(StreamFlag::External);\n>  \t}\n>\n>  \tispOutputTotal_ = outStreams.size();\n> --\n> 2.34.1\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 963DDC0DA4\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 27 Apr 2023 07:46:02 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id EF97A627DF;\n\tThu, 27 Apr 2023 09:46:01 +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 7A483627D1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 27 Apr 2023 09:46:00 +0200 (CEST)","from ideasonboard.com (unknown\n\t[IPv6:2001:b07:5d2e:52c9:1cf0:b3bc:c785:4625])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 55F7FC7E;\n\tThu, 27 Apr 2023 09:45:48 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1682581562;\n\tbh=S0gsa2LVsMMyK/en5sebwWkvGMxL0YCPwaCUBLpfELE=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=dWFC9Bomu+gw//RkzY0q4AYlbn61rfhURE2GdEMdwj1jvaLywfz9vBre0w5jJEN0R\n\tcn3rcJ80ZxhmTKNQworCanLwTpf/HQkKz5DthliX7yYqauK4Kd4wLeLP+q8O7icvcs\n\tRVflO2KJli6gbdAUp+gWI5lH32KlsBfbPEBCrzY8Jx9ZSemN0i2zHNRCIllOqN2dcx\n\tSEYMImKtGoJ0MvMpRIU9nRNMaauCohQRpKJGR+BOw+bgnhXKp9G0RttP37wO39+ikx\n\tucI/X/zUlEU1R+44IOnp7hXY2mvBNaZar4OrFnVuT3qpyRSINBSnDub8xe1XbavJkW\n\tBIy0/YW8hwGTA==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1682581548;\n\tbh=S0gsa2LVsMMyK/en5sebwWkvGMxL0YCPwaCUBLpfELE=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=ijWGcJZqtSB1A11iv1k9OCcLWX9W7C6k3OiewsWilvw/buWWAKIKQaXXt2FOR+RK0\n\tn12UsxfLO6SSzj47JNDvfp2h9I4uOsAlyI1dI0d89gECGuvA+WqOo41d/ZFq+CelVA\n\tTRMo4iiPUPRFa7T8RVLXlM+NjhKDdwKreLkx4piU="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"ijWGcJZq\"; dkim-atps=neutral","Date":"Thu, 27 Apr 2023 09:45:57 +0200","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<t2qyw7apzkbuad5w66pyf2mobskzhuaeivgy22szgfg3rg4k54@7rl6bna7a3rr>","References":"<20230426131057.21550-13-naush@raspberrypi.com>\n\t<20230427072422.695-1-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20230427072422.695-1-naush@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH] pipeline: raspberrypi: Add stream\n\tflags to RPi::Stream","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>","From":"Jacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":26971,"web_url":"https://patchwork.libcamera.org/comment/26971/","msgid":"<20230427141957.GE28489@pendragon.ideasonboard.com>","date":"2023-04-27T14:19:57","subject":"Re: [libcamera-devel] [PATCH] pipeline: raspberrypi: Add stream\n\tflags to RPi::Stream","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Naush,\n\nThank you for the patch.\n\nOn Thu, Apr 27, 2023 at 08:24:22AM +0100, Naushir Patuck via libcamera-devel wrote:\n> Add a flags_ field to indicate stream state information in RPi::Stream.\n> This replaces the existing external_ and importOnly_ boolean flags.\n> \n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> ---\n>  .../pipeline/rpi/common/pipeline_base.cpp     |  8 ++--\n>  .../pipeline/rpi/common/rpi_stream.cpp        | 40 ++++++++++--------\n>  .../pipeline/rpi/common/rpi_stream.h          | 42 ++++++++++++-------\n>  src/libcamera/pipeline/rpi/vc4/vc4.cpp        |  8 ++--\n>  4 files changed, 60 insertions(+), 38 deletions(-)\n> \n> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> index 012766b38c32..94ba3422ff0c 100644\n> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> @@ -31,6 +31,8 @@ using namespace RPi;\n>  \n>  LOG_DEFINE_CATEGORY(RPI)\n>  \n> +using StreamFlag = RPi::Stream::StreamFlag;\n> +\n>  namespace {\n>  \n>  constexpr unsigned int defaultRawBitDepth = 12;\n> @@ -504,7 +506,7 @@ int PipelineHandlerBase::configure(Camera *camera, CameraConfiguration *config)\n>  \t/* Start by freeing all buffers and reset the stream states. */\n>  \tdata->freeBuffers();\n>  \tfor (auto const stream : data->streams_)\n> -\t\tstream->setExternal(false);\n> +\t\tstream->clearFlags(StreamFlag::External);\n>  \n>  \tstd::vector<CameraData::StreamParams> rawStreams, ispStreams;\n>  \tstd::optional<BayerFormat::Packing> packing;\n> @@ -752,7 +754,7 @@ int PipelineHandlerBase::queueRequestDevice(Camera *camera, Request *request)\n>  \n>  \t/* Push all buffers supplied in the Request to the respective streams. */\n>  \tfor (auto stream : data->streams_) {\n> -\t\tif (!stream->isExternal())\n> +\t\tif (!(stream->getFlags() & StreamFlag::External))\n>  \t\t\tcontinue;\n>  \n>  \t\tFrameBuffer *buffer = request->findBuffer(stream);\n> @@ -931,7 +933,7 @@ int PipelineHandlerBase::queueAllBuffers(Camera *camera)\n>  \tint ret;\n>  \n>  \tfor (auto const stream : data->streams_) {\n> -\t\tif (!stream->isExternal()) {\n> +\t\tif (!(stream->getFlags() & StreamFlag::External)) {\n>  \t\t\tret = stream->queueAllBuffers();\n>  \t\t\tif (ret < 0)\n>  \t\t\t\treturn ret;\n> diff --git a/src/libcamera/pipeline/rpi/common/rpi_stream.cpp b/src/libcamera/pipeline/rpi/common/rpi_stream.cpp\n> index b7e4130f5e56..c158843cb0ed 100644\n> --- a/src/libcamera/pipeline/rpi/common/rpi_stream.cpp\n> +++ b/src/libcamera/pipeline/rpi/common/rpi_stream.cpp\n> @@ -14,6 +14,24 @@ LOG_DEFINE_CATEGORY(RPISTREAM)\n>  \n>  namespace RPi {\n>  \n> +void Stream::setFlags(StreamFlags flags)\n> +{\n> +\tflags_ |= flags;\n> +\n> +\t/* Import streams cannot be external. */\n> +\tASSERT(!(flags_ & StreamFlag::External) || !(flags_ & StreamFlag::ImportOnly));\n> +}\n> +\n> +void Stream::clearFlags(StreamFlags flags)\n> +{\n> +\tflags_ &= ~flags;\n> +}\n> +\n> +RPi::Stream::StreamFlags Stream::getFlags() const\n> +{\n> +\treturn flags_;\n> +}\n> +\n>  V4L2VideoDevice *Stream::dev() const\n>  {\n>  \treturn dev_.get();\n> @@ -32,18 +50,6 @@ void Stream::resetBuffers()\n>  \t\tavailableBuffers_.push(buffer.get());\n>  }\n>  \n> -void Stream::setExternal(bool external)\n> -{\n> -\t/* Import streams cannot be external. */\n> -\tASSERT(!external || !importOnly_);\n> -\texternal_ = external;\n> -}\n> -\n> -bool Stream::isExternal() const\n> -{\n> -\treturn external_;\n> -}\n> -\n>  void Stream::setExportedBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n>  {\n>  \tfor (auto const &buffer : *buffers)\n> @@ -57,7 +63,7 @@ const BufferMap &Stream::getBuffers() const\n>  \n>  unsigned int Stream::getBufferId(FrameBuffer *buffer) const\n>  {\n> -\tif (importOnly_)\n> +\tif (flags_ & StreamFlag::ImportOnly)\n>  \t\treturn 0;\n>  \n>  \t/* Find the buffer in the map, and return the buffer id. */\n> @@ -88,7 +94,7 @@ int Stream::prepareBuffers(unsigned int count)\n>  {\n>  \tint ret;\n>  \n> -\tif (!importOnly_) {\n> +\tif (!(flags_ & StreamFlag::ImportOnly)) {\n>  \t\tif (count) {\n>  \t\t\t/* Export some frame buffers for internal use. */\n>  \t\t\tret = dev_->exportBuffers(count, &internalBuffers_);\n> @@ -113,7 +119,7 @@ int Stream::prepareBuffers(unsigned int count)\n>  \t * \\todo Find a better heuristic, or, even better, an exact solution to\n>  \t * this issue.\n>  \t */\n> -\tif (isExternal() || importOnly_)\n> +\tif ((flags_ & StreamFlag::External) || (flags_ & StreamFlag::ImportOnly))\n>  \t\tcount = count * 2;\n>  \n>  \treturn dev_->importBuffers(count);\n> @@ -160,7 +166,7 @@ int Stream::queueBuffer(FrameBuffer *buffer)\n>  \n>  void Stream::returnBuffer(FrameBuffer *buffer)\n>  {\n> -\tif (!external_) {\n> +\tif (!(flags_ & StreamFlag::External)) {\n>  \t\t/* For internal buffers, simply requeue back to the device. */\n>  \t\tqueueToDevice(buffer);\n>  \t\treturn;\n> @@ -204,7 +210,7 @@ int Stream::queueAllBuffers()\n>  {\n>  \tint ret;\n>  \n> -\tif (external_)\n> +\tif (flags_ & StreamFlag::External)\n>  \t\treturn 0;\n>  \n>  \twhile (!availableBuffers_.empty()) {\n> diff --git a/src/libcamera/pipeline/rpi/common/rpi_stream.h b/src/libcamera/pipeline/rpi/common/rpi_stream.h\n> index b8c74de35863..6edd304bdfe2 100644\n> --- a/src/libcamera/pipeline/rpi/common/rpi_stream.h\n> +++ b/src/libcamera/pipeline/rpi/common/rpi_stream.h\n> @@ -12,6 +12,7 @@\n>  #include <unordered_map>\n>  #include <vector>\n>  \n> +#include <libcamera/base/flags.h>\n>  #include <libcamera/stream.h>\n>  \n>  #include \"libcamera/internal/v4l2_videodevice.h\"\n> @@ -37,25 +38,41 @@ enum BufferMask {\n>  class Stream : public libcamera::Stream\n>  {\n>  public:\n> +\tenum class StreamFlag {\n> +\t\tNone\t\t= 0,\n> +\t\t/*\n> +\t\t * Indicates that this stream only imports buffers, e.g. the ISP\n> +\t\t * input stream.\n> +\t\t */\n> +\t\tImportOnly\t= (1 << 0),\n> +\t\t/*\n> +\t\t * Indicates that this stream is active externally, i.e. the\n> +\t\t * buffers might be provided by (and returned to) the application.\n> +\t\t */\n\nThe documentation, despite being short, helps a lot to understand\nstream handling ! Thank you for this.\n\n> +\t\tExternal\t= (1 << 1),\n> +\t};\n> +\n> +\tusing StreamFlags = Flags<StreamFlag>;\n> +\n>  \tStream()\n> -\t\t: id_(BufferMask::MaskID)\n> +\t\t: flags_(StreamFlag::None), id_(BufferMask::MaskID)\n>  \t{\n>  \t}\n>  \n> -\tStream(const char *name, MediaEntity *dev, bool importOnly = false)\n> -\t\t: external_(false), importOnly_(importOnly), name_(name),\n> +\tStream(const char *name, MediaEntity *dev, StreamFlags flags = StreamFlag::None)\n> +\t\t: flags_(flags), name_(name),\n>  \t\t  dev_(std::make_unique<V4L2VideoDevice>(dev)), id_(BufferMask::MaskID)\n>  \t{\n>  \t}\n>  \n> +\tvoid setFlags(StreamFlags flags);\n> +\tvoid clearFlags(StreamFlags flags);\n> +\tStreamFlags getFlags() const;\n\nWe usually don't prefix getters with 'get', this should be flags().\n\n> +\n>  \tV4L2VideoDevice *dev() const;\n>  \tconst std::string &name() const;\n> -\tbool isImporter() const;\n>  \tvoid resetBuffers();\n>  \n> -\tvoid setExternal(bool external);\n> -\tbool isExternal() const;\n\nI think I would have kept these accessors instead of adding generic\nsetFlags()/clearFlags()/getFlags() accessors, I find these more\nreadable. I don't care much though, you can ignore this comment,\nespecially if you think you may add other flags in the future.\n\nWith the getter renamed,\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> -\n>  \tvoid setExportedBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n>  \tconst BufferMap &getBuffers() const;\n>  \tunsigned int getBufferId(FrameBuffer *buffer) const;\n> @@ -112,14 +129,7 @@ private:\n>  \tvoid clearBuffers();\n>  \tint queueToDevice(FrameBuffer *buffer);\n>  \n> -\t/*\n> -\t * Indicates that this stream is active externally, i.e. the buffers\n> -\t * might be provided by (and returned to) the application.\n> -\t */\n> -\tbool external_;\n> -\n> -\t/* Indicates that this stream only imports buffers, e.g. ISP input. */\n> -\tbool importOnly_;\n> +\tStreamFlags flags_;\n>  \n>  \t/* Stream name identifier. */\n>  \tstd::string name_;\n> @@ -182,4 +192,6 @@ public:\n>  \n>  } /* namespace RPi */\n>  \n> +LIBCAMERA_FLAGS_ENABLE_OPERATORS(RPi::Stream::StreamFlag)\n> +\n>  } /* namespace libcamera */\n> diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> index a085a06376a8..7a3445865987 100644\n> --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n> @@ -23,6 +23,8 @@ namespace libcamera {\n>  \n>  LOG_DECLARE_CATEGORY(RPI)\n>  \n> +using StreamFlag = RPi::Stream::StreamFlag;\n> +\n>  namespace {\n>  \n>  enum class Unicam : unsigned int { Image, Embedded };\n> @@ -320,7 +322,7 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer\n>  \t}\n>  \n>  \t/* Tag the ISP input stream as an import stream. */\n> -\tdata->isp_[Isp::Input] = RPi::Stream(\"ISP Input\", ispOutput0, true);\n> +\tdata->isp_[Isp::Input] = RPi::Stream(\"ISP Input\", ispOutput0, StreamFlag::ImportOnly);\n>  \tdata->isp_[Isp::Output0] = RPi::Stream(\"ISP Output0\", ispCapture1);\n>  \tdata->isp_[Isp::Output1] = RPi::Stream(\"ISP Output1\", ispCapture2);\n>  \tdata->isp_[Isp::Stats] = RPi::Stream(\"ISP Stats\", ispCapture3);\n> @@ -502,7 +504,7 @@ int Vc4CameraData::platformConfigure(const V4L2SubdeviceFormat &sensorFormat,\n>  \t */\n>  \tif (!rawStreams.empty()) {\n>  \t\trawStreams[0].cfg->setStream(&unicam_[Unicam::Image]);\n> -\t\tunicam_[Unicam::Image].setExternal(true);\n> +\t\tunicam_[Unicam::Image].setFlags(StreamFlag::External);\n>  \t}\n>  \n>  \tret = isp_[Isp::Input].dev()->setFormat(&unicamFormat);\n> @@ -547,7 +549,7 @@ int Vc4CameraData::platformConfigure(const V4L2SubdeviceFormat &sensorFormat,\n>  \t\t\t<< ColorSpace::toString(cfg->colorSpace);\n>  \n>  \t\tcfg->setStream(stream);\n> -\t\tstream->setExternal(true);\n> +\t\tstream->setFlags(StreamFlag::External);\n>  \t}\n>  \n>  \tispOutputTotal_ = outStreams.size();","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 9C910C0DA4\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 27 Apr 2023 14:19:48 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 285F0627D6;\n\tThu, 27 Apr 2023 16:19:48 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8495C627B7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 27 Apr 2023 16:19:46 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(133-32-181-51.west.xps.vectant.ne.jp [133.32.181.51])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id AF54E802;\n\tThu, 27 Apr 2023 16:19:33 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1682605188;\n\tbh=ExpsK9XnIB6u5OddsRS2dpSMHjCkz4z6ALGgr5wgNsQ=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=hJZQsOKbWATbnPJYhwlxgllxenJfPjEYuDAJ9s6lAQ13NQH1ZhqPz5zumMOmOvA48\n\tqVPLi0LfqaAa1I98bVHd6LhCTIWdY1FXeikMN4DDXxtnNVrLHLC4k/NJDh4GqQuik7\n\t5v9Etho9ckPKZap1Xg9jXPusxDI9q0976aqHa9B0ZAvzfQLEa0dGMveS5dAe+aI3J9\n\t23ykmfUfMZkVKm/ndzMnoJcc97tkRNb+WTL2EktZ4rjrMjyEm0n16jVPM3M3fK837b\n\tUQcDb2emcWJLc0524AaUwGSV4/Wvb4ve3zG33NIyJiFF9FLL5zlw1jZdL4Qhz3yuG9\n\tnaKDY13hdQhWw==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1682605174;\n\tbh=ExpsK9XnIB6u5OddsRS2dpSMHjCkz4z6ALGgr5wgNsQ=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=dSuO+uAEeIGWkSSLoa8qEiGbYm3yq9fmP4Oty8DUfgY7P/Mlqwoj89LL6FVk/k/Lm\n\tLHaydC8a8Hs/tLsTK1x6rnURKP3BUocHToArfMzLgd32b8rZENLgm0ZkQchOFVV4dO\n\t2EqsEA960WVZPgW+BUeW2YGgErZI37Lw6b6Iv/HI="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"dSuO+uAE\"; dkim-atps=neutral","Date":"Thu, 27 Apr 2023 17:19:57 +0300","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<20230427141957.GE28489@pendragon.ideasonboard.com>","References":"<20230426131057.21550-13-naush@raspberrypi.com>\n\t<20230427072422.695-1-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20230427072422.695-1-naush@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH] pipeline: raspberrypi: Add stream\n\tflags to RPi::Stream","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>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]