[{"id":11358,"web_url":"https://patchwork.libcamera.org/comment/11358/","msgid":"<20200713112637.GC2866302@oden.dyn.berto.se>","date":"2020-07-13T11:26:37","subject":"Re: [libcamera-devel] [PATCH 1/9] libcamera: pipeline: raspberrypi:\n\tMove RPiStream into a separate header","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Naushir,\n\nThanks for your work.\n\nOn 2020-07-13 09:47:20 +0100, Naushir Patuck wrote:\n> Put RPiStream into the RPi namespace and add a new log category (RPISTREAM)\n\nI would add that there is no functional change in this patch.\n\n> \n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> ---\n>  .../pipeline/raspberrypi/raspberrypi.cpp      | 189 ++----------------\n>  .../pipeline/raspberrypi/rpi_stream.h         | 182 +++++++++++++++++\n\nI wonder if it would make sens to move some of the code to a\nrpi_stream.cpp file?\n\n>  2 files changed, 199 insertions(+), 172 deletions(-)\n>  create mode 100644 src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> \n> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> index a08ad6a8..7bae72f9 100644\n> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> @@ -17,7 +17,6 @@\n>  #include <libcamera/ipa/raspberrypi.h>\n>  #include <libcamera/logging.h>\n>  #include <libcamera/request.h>\n> -#include <libcamera/stream.h>\n>  \n>  #include <linux/videodev2.h>\n>  \n> @@ -30,6 +29,7 @@\n>  #include \"libcamera/internal/v4l2_controls.h\"\n>  #include \"libcamera/internal/v4l2_videodevice.h\"\n>  \n> +#include \"rpi_stream.h\"\n>  #include \"staggered_ctrl.h\"\n>  #include \"vcsm.h\"\n>  \n> @@ -121,165 +121,10 @@ V4L2DeviceFormat findBestMode(V4L2PixFmtMap &formatsMap, const Size &req)\n>  \treturn bestMode;\n>  }\n>  \n> -} /* namespace */\n> -\n> -/*\n> - * Device stream abstraction for either an internal or external stream.\n> - * Used for both Unicam and the ISP.\n> - */\n> -class RPiStream : public Stream\n> -{\n> -public:\n> -\tRPiStream()\n> -\t{\n> -\t}\n> -\n> -\tRPiStream(const char *name, MediaEntity *dev, bool importOnly = false)\n> -\t\t: external_(false), importOnly_(importOnly), name_(name),\n> -\t\t  dev_(std::make_unique<V4L2VideoDevice>(dev))\n> -\t{\n> -\t}\n> -\n> -\tV4L2VideoDevice *dev() const\n> -\t{\n> -\t\treturn dev_.get();\n> -\t}\n> -\n> -\tvoid setExternal(bool external)\n> -\t{\n> -\t\texternal_ = external;\n> -\t}\n> -\n> -\tbool isExternal() const\n> -\t{\n> -\t\t/*\n> -\t\t * Import streams cannot be external.\n> -\t\t *\n> -\t\t * RAW capture is a special case where we simply copy the RAW\n> -\t\t * buffer out of the request. All other buffer handling happens\n> -\t\t * as if the stream is internal.\n> -\t\t */\n> -\t\treturn external_ && !importOnly_;\n> -\t}\n> -\n> -\tbool isImporter() const\n> -\t{\n> -\t\treturn importOnly_;\n> -\t}\n> -\n> -\tvoid reset()\n> -\t{\n> -\t\texternal_ = false;\n> -\t\tinternalBuffers_.clear();\n> -\t}\n> -\n> -\tstd::string name() const\n> -\t{\n> -\t\treturn name_;\n> -\t}\n> -\n> -\tvoid setExternalBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n> -\t{\n> -\t\texternalBuffers_ = buffers;\n> -\t}\n> -\n> -\tconst std::vector<std::unique_ptr<FrameBuffer>> *getBuffers() const\n> -\t{\n> -\t\treturn external_ ? externalBuffers_ : &internalBuffers_;\n> -\t}\n> -\n> -\tvoid releaseBuffers()\n> -\t{\n> -\t\tdev_->releaseBuffers();\n> -\t\tif (!external_ && !importOnly_)\n> -\t\t\tinternalBuffers_.clear();\n> -\t}\n> -\n> -\tint importBuffers(unsigned int count)\n> -\t{\n> -\t\treturn dev_->importBuffers(count);\n> -\t}\n> -\n> -\tint allocateBuffers(unsigned int count)\n> -\t{\n> -\t\treturn dev_->allocateBuffers(count, &internalBuffers_);\n> -\t}\n> -\n> -\tint queueBuffers()\n> -\t{\n> -\t\tif (external_)\n> -\t\t\treturn 0;\n> -\n> -\t\tfor (auto &b : internalBuffers_) {\n> -\t\t\tint ret = dev_->queueBuffer(b.get());\n> -\t\t\tif (ret) {\n> -\t\t\t\tLOG(RPI, Error) << \"Failed to queue buffers for \"\n> -\t\t\t\t\t\t<< name_;\n> -\t\t\t\treturn ret;\n> -\t\t\t}\n> -\t\t}\n> -\n> -\t\treturn 0;\n> -\t}\n> -\n> -\tbool findFrameBuffer(FrameBuffer *buffer) const\n> -\t{\n> -\t\tauto start = external_ ? externalBuffers_->begin() : internalBuffers_.begin();\n> -\t\tauto end = external_ ? externalBuffers_->end() : internalBuffers_.end();\n> -\n> -\t\tif (importOnly_)\n> -\t\t\treturn false;\n> -\n> -\t\tif (std::find_if(start, end,\n> -\t\t\t\t [buffer](std::unique_ptr<FrameBuffer> const &ref) { return ref.get() == buffer; }) != end)\n> -\t\t\treturn true;\n> -\n> -\t\treturn false;\n> -\t}\n> -\n> -private:\n> -\t/*\n> -\t * Indicates that this stream is active externally, i.e. the buffers\n> -\t * are provided by the application.\n> -\t */\n> -\tbool external_;\n> -\t/* Indicates that this stream only imports buffers, e.g. ISP input. */\n> -\tbool importOnly_;\n> -\t/* Stream name identifier. */\n> -\tstd::string name_;\n> -\t/* The actual device stream. */\n> -\tstd::unique_ptr<V4L2VideoDevice> dev_;\n> -\t/* Internally allocated framebuffers associated with this device stream. */\n> -\tstd::vector<std::unique_ptr<FrameBuffer>> internalBuffers_;\n> -\t/* Externally allocated framebuffers associated with this device stream. */\n> -\tstd::vector<std::unique_ptr<FrameBuffer>> *externalBuffers_;\n> -};\n> -\n> -/*\n> - * The following class is just a convenient (and typesafe) array of device\n> - * streams indexed with an enum class.\n> - */\n>  enum class Unicam : unsigned int { Image, Embedded };\n>  enum class Isp : unsigned int { Input, Output0, Output1, Stats };\n>  \n> -template<typename E, std::size_t N>\n> -class RPiDevice : public std::array<class RPiStream, N>\n> -{\n> -private:\n> -\tconstexpr auto index(E e) const noexcept\n> -\t{\n> -\t\treturn static_cast<std::underlying_type_t<E>>(e);\n> -\t}\n> -public:\n> -\tRPiStream &operator[](E e)\n> -\t{\n> -\t\treturn std::array<class RPiStream, N>::operator[](index(e));\n> -\t}\n> -\tconst RPiStream &operator[](E e) const\n> -\t{\n> -\t\treturn std::array<class RPiStream, N>::operator[](index(e));\n> -\t}\n> -};\n> +} /* namespace */\n>  \n>  class RPiCameraData : public CameraData\n>  {\n> @@ -318,7 +163,7 @@ public:\n>  \tvoid ispOutputDequeue(FrameBuffer *buffer);\n>  \n>  \tvoid clearIncompleteRequests();\n> -\tvoid handleStreamBuffer(FrameBuffer *buffer, const RPiStream *stream);\n> +\tvoid handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream);\n>  \tvoid handleState();\n>  \n>  \tCameraSensor *sensor_;\n> @@ -326,7 +171,7 @@ public:\n>  \tRPiDevice<Unicam, 2> unicam_;\n>  \tRPiDevice<Isp, 4> isp_;\n>  \t/* The vector below is just for convenience when iterating over all streams. */\n> -\tstd::vector<RPiStream *> streams_;\n> +\tstd::vector<RPi::RPiStream *> streams_;\n>  \t/* Buffers passed to the IPA. */\n>  \tstd::vector<IPABuffer> ipaBuffers_;\n>  \n> @@ -782,7 +627,7 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)\n>  int PipelineHandlerRPi::exportFrameBuffers(Camera *camera, Stream *stream,\n>  \t\t\t\t\t   std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n>  {\n> -\tRPiStream *s = static_cast<RPiStream *>(stream);\n> +\tRPi::RPiStream *s = static_cast<RPi::RPiStream *>(stream);\n>  \tunsigned int count = stream->configuration().bufferCount;\n>  \tint ret = s->dev()->exportBuffers(count, buffers);\n>  \n> @@ -914,14 +759,14 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)\n>  \tstd::unique_ptr<RPiCameraData> data = std::make_unique<RPiCameraData>(this);\n>  \n>  \t/* Locate and open the unicam video streams. */\n> -\tdata->unicam_[Unicam::Embedded] = RPiStream(\"Unicam Embedded\", unicam_->getEntityByName(\"unicam-embedded\"));\n> -\tdata->unicam_[Unicam::Image] = RPiStream(\"Unicam Image\", unicam_->getEntityByName(\"unicam-image\"));\n> +\tdata->unicam_[Unicam::Embedded] = RPi::RPiStream(\"Unicam Embedded\", unicam_->getEntityByName(\"unicam-embedded\"));\n> +\tdata->unicam_[Unicam::Image] = RPi::RPiStream(\"Unicam Image\", unicam_->getEntityByName(\"unicam-image\"));\n>  \n>  \t/* Tag the ISP input stream as an import stream. */\n> -\tdata->isp_[Isp::Input] = RPiStream(\"ISP Input\", isp_->getEntityByName(\"bcm2835-isp0-output0\"), true);\n> -\tdata->isp_[Isp::Output0] = RPiStream(\"ISP Output0\", isp_->getEntityByName(\"bcm2835-isp0-capture1\"));\n> -\tdata->isp_[Isp::Output1] = RPiStream(\"ISP Output1\", isp_->getEntityByName(\"bcm2835-isp0-capture2\"));\n> -\tdata->isp_[Isp::Stats] = RPiStream(\"ISP Stats\", isp_->getEntityByName(\"bcm2835-isp0-capture3\"));\n> +\tdata->isp_[Isp::Input] = RPi::RPiStream(\"ISP Input\", isp_->getEntityByName(\"bcm2835-isp0-output0\"), true);\n> +\tdata->isp_[Isp::Output0] = RPi::RPiStream(\"ISP Output0\", isp_->getEntityByName(\"bcm2835-isp0-capture1\"));\n> +\tdata->isp_[Isp::Output1] = RPi::RPiStream(\"ISP Output1\", isp_->getEntityByName(\"bcm2835-isp0-capture2\"));\n> +\tdata->isp_[Isp::Stats] = RPi::RPiStream(\"ISP Stats\", isp_->getEntityByName(\"bcm2835-isp0-capture3\"));\n>  \n>  \t/* This is just for convenience so that we can easily iterate over all streams. */\n>  \tfor (auto &stream : data->unicam_)\n> @@ -1070,7 +915,7 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera)\n>  \t */\n>  \tunsigned int maxBuffers = 0;\n>  \tfor (const Stream *s : camera->streams())\n> -\t\tif (static_cast<const RPiStream *>(s)->isExternal())\n> +\t\tif (static_cast<const RPi::RPiStream *>(s)->isExternal())\n>  \t\t\tmaxBuffers = std::max(maxBuffers, s->configuration().bufferCount);\n>  \n>  \tfor (auto const stream : data->streams_) {\n> @@ -1271,12 +1116,12 @@ done:\n>  \n>  void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer)\n>  {\n> -\tconst RPiStream *stream = nullptr;\n> +\tconst RPi::RPiStream *stream = nullptr;\n>  \n>  \tif (state_ == State::Stopped)\n>  \t\treturn;\n>  \n> -\tfor (RPiStream const &s : unicam_) {\n> +\tfor (RPi::RPiStream const &s : unicam_) {\n>  \t\tif (s.findFrameBuffer(buffer)) {\n>  \t\t\tstream = &s;\n>  \t\t\tbreak;\n> @@ -1332,12 +1177,12 @@ void RPiCameraData::ispInputDequeue(FrameBuffer *buffer)\n>  \n>  void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer)\n>  {\n> -\tconst RPiStream *stream = nullptr;\n> +\tconst RPi::RPiStream *stream = nullptr;\n>  \n>  \tif (state_ == State::Stopped)\n>  \t\treturn;\n>  \n> -\tfor (RPiStream const &s : isp_) {\n> +\tfor (RPi::RPiStream const &s : isp_) {\n>  \t\tif (s.findFrameBuffer(buffer)) {\n>  \t\t\tstream = &s;\n>  \t\t\tbreak;\n> @@ -1418,7 +1263,7 @@ void RPiCameraData::clearIncompleteRequests()\n>  \t}\n>  }\n>  \n> -void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPiStream *stream)\n> +void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream)\n>  {\n>  \tif (stream->isExternal()) {\n>  \t\tif (!dropFrame_) {\n> diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> new file mode 100644\n> index 00000000..ed4f4987\n> --- /dev/null\n> +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> @@ -0,0 +1,182 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2020, Raspberry Pi (Trading) Ltd.\n> + *\n> + * rpi_stream.h - Raspberry Pi device stream abstraction class.\n> + */\n> +#ifndef __LIBCAMERA_PIPELINE_RPI_STREAM_H__\n> +#define __LIBCAMERA_PIPELINE_RPI_STREAM_H__\n> +\n> +#include <queue>\n> +#include <string>\n> +#include <vector>\n> +\n> +#include \"libcamera/internal/v4l2_videodevice.h\"\n> +#include <libcamera/stream.h>\n> +\n> +namespace libcamera {\n> +\n> +LOG_DEFINE_CATEGORY(RPISTREAM)\n> +\n> +namespace RPi {\n> +\n> +/*\n> + * Device stream abstraction for either an internal or external stream.\n> + * Used for both Unicam and the ISP.\n> + */\n> +class RPiStream : public Stream\n> +{\n> +public:\n> +\tRPiStream()\n> +\t{\n> +\t}\n> +\n> +\tRPiStream(const char *name, MediaEntity *dev, bool importOnly = false)\n> +\t\t: external_(false), importOnly_(importOnly), name_(name),\n> +\t\t  dev_(std::make_unique<V4L2VideoDevice>(dev))\n> +\t{\n> +\t}\n> +\n> +\tV4L2VideoDevice *dev() const\n> +\t{\n> +\t\treturn dev_.get();\n> +\t}\n> +\n> +\tvoid setExternal(bool external)\n> +\t{\n> +\t\texternal_ = external;\n> +\t}\n> +\n> +\tbool isExternal() const\n> +\t{\n> +\t\t/*\n> +\t\t * Import streams cannot be external.\n> +\t\t *\n> +\t\t * RAW capture is a special case where we simply copy the RAW\n> +\t\t * buffer out of the request. All other buffer handling happens\n> +\t\t * as if the stream is internal.\n> +\t\t */\n> +\t\treturn external_ && !importOnly_;\n> +\t}\n> +\n> +\tbool isImporter() const\n> +\t{\n> +\t\treturn importOnly_;\n> +\t}\n> +\n> +\tvoid reset()\n> +\t{\n> +\t\texternal_ = false;\n> +\t\tinternalBuffers_.clear();\n> +\t}\n> +\n> +\tstd::string name() const\n> +\t{\n> +\t\treturn name_;\n> +\t}\n> +\n> +\tvoid setExternalBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n> +\t{\n> +\t\texternalBuffers_ = buffers;\n> +\t}\n> +\n> +\tconst std::vector<std::unique_ptr<FrameBuffer>> *getBuffers() const\n> +\t{\n> +\t\treturn external_ ? externalBuffers_ : &internalBuffers_;\n> +\t}\n> +\n> +\tvoid releaseBuffers()\n> +\t{\n> +\t\tdev_->releaseBuffers();\n> +\t\tif (!external_ && !importOnly_)\n> +\t\t\tinternalBuffers_.clear();\n> +\t}\n> +\n> +\tint importBuffers(unsigned int count)\n> +\t{\n> +\t\treturn dev_->importBuffers(count);\n> +\t}\n> +\n> +\tint allocateBuffers(unsigned int count)\n> +\t{\n> +\t\treturn dev_->allocateBuffers(count, &internalBuffers_);\n> +\t}\n> +\n> +\tint queueBuffers()\n> +\t{\n> +\t\tif (external_)\n> +\t\t\treturn 0;\n> +\n> +\t\tfor (auto &b : internalBuffers_) {\n> +\t\t\tint ret = dev_->queueBuffer(b.get());\n> +\t\t\tif (ret) {\n> +\t\t\t\tLOG(RPISTREAM, Error) << \"Failed to queue buffers for \"\n> +\t\t\t\t\t\t      << name_;\n> +\t\t\t\treturn ret;\n> +\t\t\t}\n> +\t\t}\n> +\n> +\t\treturn 0;\n> +\t}\n> +\n> +\tbool findFrameBuffer(FrameBuffer *buffer) const\n> +\t{\n> +\t\tauto start = external_ ? externalBuffers_->begin() : internalBuffers_.begin();\n> +\t\tauto end = external_ ? externalBuffers_->end() : internalBuffers_.end();\n> +\n> +\t\tif (importOnly_)\n> +\t\t\treturn false;\n> +\n> +\t\tif (std::find_if(start, end,\n> +\t\t\t\t [buffer](std::unique_ptr<FrameBuffer> const &ref) { return ref.get() == buffer; }) != end)\n> +\t\t\treturn true;\n> +\n> +\t\treturn false;\n> +\t}\n> +\n> +private:\n> +\t/*\n> +\t * Indicates that this stream is active externally, i.e. the buffers\n> +\t * are provided by the application.\n> +\t */\n> +\tbool external_;\n> +\t/* Indicates that this stream only imports buffers, e.g. ISP input. */\n> +\tbool importOnly_;\n> +\t/* Stream name identifier. */\n> +\tstd::string name_;\n> +\t/* The actual device stream. */\n> +\tstd::unique_ptr<V4L2VideoDevice> dev_;\n> +\t/* Internally allocated framebuffers associated with this device stream. */\n> +\tstd::vector<std::unique_ptr<FrameBuffer>> internalBuffers_;\n> +\t/* Externally allocated framebuffers associated with this device stream. */\n> +\tstd::vector<std::unique_ptr<FrameBuffer>> *externalBuffers_;\n> +};\n> +\n> +/*\n> + * The following class is just a convenient (and typesafe) array of device\n> + * streams indexed with an enum class.\n> + */\n> +template<typename E, std::size_t N>\n> +class RPiDevice : public std::array<class RPiStream, N>\n> +{\n> +private:\n> +\tconstexpr auto index(E e) const noexcept\n> +\t{\n> +\t\treturn static_cast<std::underlying_type_t<E>>(e);\n> +\t}\n> +public:\n> +\tRPiStream &operator[](E e)\n> +\t{\n> +\t\treturn std::array<class RPiStream, N>::operator[](index(e));\n> +\t}\n> +\tconst RPiStream &operator[](E e) const\n> +\t{\n> +\t\treturn std::array<class RPiStream, N>::operator[](index(e));\n> +\t}\n> +};\n> +\n> +} /* namespace RPi */\n> +\n> +} /* namespace libcamera */\n> +\n> +#endif /* __LIBCAMERA_PIPELINE_RPI_STREAM_H__ */\n> -- \n> 2.25.1\n> \n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","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 F2C30BD790\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 13 Jul 2020 11:26:41 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6BA90605C5;\n\tMon, 13 Jul 2020 13:26:41 +0200 (CEST)","from mail-lf1-x12e.google.com (mail-lf1-x12e.google.com\n\t[IPv6:2a00:1450:4864:20::12e])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C1D55603A4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 13 Jul 2020 13:26:39 +0200 (CEST)","by mail-lf1-x12e.google.com with SMTP id u25so8757934lfm.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 13 Jul 2020 04:26:39 -0700 (PDT)","from localhost (h-209-203.A463.priv.bahnhof.se. [155.4.209.203])\n\tby smtp.gmail.com with ESMTPSA id\n\te9sm4009249ljn.61.2020.07.13.04.26.38\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 13 Jul 2020 04:26:38 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=ragnatech-se.20150623.gappssmtp.com\n\theader.i=@ragnatech-se.20150623.gappssmtp.com\n\theader.b=\"qFJHcZyu\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to;\n\tbh=6HYZ2kS1CtNcagg23tiwkP9ZJTrpqP1uKtB2jXU4tdg=;\n\tb=qFJHcZyu4Xu2NEAb4XdJPIgn+JVp1rKSg33ZupyXBQiqN9zmT49/L/gwXDHRq9gXfk\n\t/d8ZgV9af6rl88qdIXR85Yj9NLYzuSkeOvBLbO3zMIoxicCUoPyNwwBMW7F3e4IuVr8Y\n\tpM0E6VKX00Sqj41Tg5TsbXVxZH5PBvcvYmMMZkEqCuvsuuadR6trz1SIheObQnrwl9dB\n\tctoIKDAdDvYwnm/Kaw3ilQpTo+cKty4beN3yRy2ijc3IXnkcswjSSdDIBSomZlbwGGR5\n\tQ+io4PnN0U3CouLXoqn8gVDrkSL0XBDHuAxIn1jvOIatD+Jdf8/jpmxVYg6isxrmsG5i\n\tEh8Q==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to;\n\tbh=6HYZ2kS1CtNcagg23tiwkP9ZJTrpqP1uKtB2jXU4tdg=;\n\tb=lBKJZspGvq2MfIGWYEy1fQEuvtfT0zWVxoJISXZQ2VxMfSGhQjaRScNdI0mbsqWbNp\n\tr/hiv3UBEL7MnjnHwlXAAB3hDTENTWT+Yt0gnvboVgpirgKLjD47Z2TMpnbK9Iv17UzE\n\tvnJMFsJeKP8C8L7RQFhOmIJ1BBiuae+Ir2EEhLkdo3nOa6GnzBYCkoaTpdxKz8Tt6YL0\n\tS5ziMAmk2fhtpza73HthvKojc+UAfEFTicT+PnF/KwDtg2kSN+T6zyQroG2QRIi+1cLX\n\thibSdYXrKK9AkKK7NE6mu0hAld0gZrTv+kaAT4F7T1E8NY7KJKLBofG6SjkwlExUPR0H\n\taYEA==","X-Gm-Message-State":"AOAM532hfJKLPGj0rubZ0Bm//u9FjFO4oXo4eNdQJrpU4tGnkmOs+zvJ\n\tFmUmryEG/+dZxS1wTq+f92AM6g==","X-Google-Smtp-Source":"ABdhPJw7vJ/5lqZ6TuR2jQXB7snO6fyqVXxGu4f6TSUQ5UNJUITwPgLVMfECOJn9jecazSMNKNTpnw==","X-Received":"by 2002:a19:ccc5:: with SMTP id\n\tc188mr52542576lfg.163.1594639598797; \n\tMon, 13 Jul 2020 04:26:38 -0700 (PDT)","Date":"Mon, 13 Jul 2020 13:26:37 +0200","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<20200713112637.GC2866302@oden.dyn.berto.se>","References":"<20200713084727.232422-1-naush@raspberrypi.com>\n\t<20200713084727.232422-2-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20200713084727.232422-2-naush@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH 1/9] libcamera: pipeline: raspberrypi:\n\tMove RPiStream into a separate header","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":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"iso-8859-1\"","Content-Transfer-Encoding":"quoted-printable","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":11361,"web_url":"https://patchwork.libcamera.org/comment/11361/","msgid":"<CAEmqJPo3MX5M4xVJ-Xt13hYUURZU+j5avwkEB4TZd78prUfstA@mail.gmail.com>","date":"2020-07-13T11:32:25","subject":"Re: [libcamera-devel] [PATCH 1/9] libcamera: pipeline: raspberrypi:\n\tMove RPiStream into a separate header","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Niklas,\n\nOn Mon, 13 Jul 2020 at 12:26, Niklas Söderlund\n<niklas.soderlund@ragnatech.se> wrote:\n>\n> Hi Naushir,\n>\n> Thanks for your work.\n>\n> On 2020-07-13 09:47:20 +0100, Naushir Patuck wrote:\n> > Put RPiStream into the RPi namespace and add a new log category (RPISTREAM)\n>\n> I would add that there is no functional change in this patch.\n>\n> >\n> > Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> > ---\n> >  .../pipeline/raspberrypi/raspberrypi.cpp      | 189 ++----------------\n> >  .../pipeline/raspberrypi/rpi_stream.h         | 182 +++++++++++++++++\n>\n> I wonder if it would make sens to move some of the code to a\n> rpi_stream.cpp file?\n\nIndeed you are correct.  Please see patch 9 :)\n\nRegards,\nNaush\n\n>\n> >  2 files changed, 199 insertions(+), 172 deletions(-)\n> >  create mode 100644 src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> >\n> > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > index a08ad6a8..7bae72f9 100644\n> > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > @@ -17,7 +17,6 @@\n> >  #include <libcamera/ipa/raspberrypi.h>\n> >  #include <libcamera/logging.h>\n> >  #include <libcamera/request.h>\n> > -#include <libcamera/stream.h>\n> >\n> >  #include <linux/videodev2.h>\n> >\n> > @@ -30,6 +29,7 @@\n> >  #include \"libcamera/internal/v4l2_controls.h\"\n> >  #include \"libcamera/internal/v4l2_videodevice.h\"\n> >\n> > +#include \"rpi_stream.h\"\n> >  #include \"staggered_ctrl.h\"\n> >  #include \"vcsm.h\"\n> >\n> > @@ -121,165 +121,10 @@ V4L2DeviceFormat findBestMode(V4L2PixFmtMap &formatsMap, const Size &req)\n> >       return bestMode;\n> >  }\n> >\n> > -} /* namespace */\n> > -\n> > -/*\n> > - * Device stream abstraction for either an internal or external stream.\n> > - * Used for both Unicam and the ISP.\n> > - */\n> > -class RPiStream : public Stream\n> > -{\n> > -public:\n> > -     RPiStream()\n> > -     {\n> > -     }\n> > -\n> > -     RPiStream(const char *name, MediaEntity *dev, bool importOnly = false)\n> > -             : external_(false), importOnly_(importOnly), name_(name),\n> > -               dev_(std::make_unique<V4L2VideoDevice>(dev))\n> > -     {\n> > -     }\n> > -\n> > -     V4L2VideoDevice *dev() const\n> > -     {\n> > -             return dev_.get();\n> > -     }\n> > -\n> > -     void setExternal(bool external)\n> > -     {\n> > -             external_ = external;\n> > -     }\n> > -\n> > -     bool isExternal() const\n> > -     {\n> > -             /*\n> > -              * Import streams cannot be external.\n> > -              *\n> > -              * RAW capture is a special case where we simply copy the RAW\n> > -              * buffer out of the request. All other buffer handling happens\n> > -              * as if the stream is internal.\n> > -              */\n> > -             return external_ && !importOnly_;\n> > -     }\n> > -\n> > -     bool isImporter() const\n> > -     {\n> > -             return importOnly_;\n> > -     }\n> > -\n> > -     void reset()\n> > -     {\n> > -             external_ = false;\n> > -             internalBuffers_.clear();\n> > -     }\n> > -\n> > -     std::string name() const\n> > -     {\n> > -             return name_;\n> > -     }\n> > -\n> > -     void setExternalBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n> > -     {\n> > -             externalBuffers_ = buffers;\n> > -     }\n> > -\n> > -     const std::vector<std::unique_ptr<FrameBuffer>> *getBuffers() const\n> > -     {\n> > -             return external_ ? externalBuffers_ : &internalBuffers_;\n> > -     }\n> > -\n> > -     void releaseBuffers()\n> > -     {\n> > -             dev_->releaseBuffers();\n> > -             if (!external_ && !importOnly_)\n> > -                     internalBuffers_.clear();\n> > -     }\n> > -\n> > -     int importBuffers(unsigned int count)\n> > -     {\n> > -             return dev_->importBuffers(count);\n> > -     }\n> > -\n> > -     int allocateBuffers(unsigned int count)\n> > -     {\n> > -             return dev_->allocateBuffers(count, &internalBuffers_);\n> > -     }\n> > -\n> > -     int queueBuffers()\n> > -     {\n> > -             if (external_)\n> > -                     return 0;\n> > -\n> > -             for (auto &b : internalBuffers_) {\n> > -                     int ret = dev_->queueBuffer(b.get());\n> > -                     if (ret) {\n> > -                             LOG(RPI, Error) << \"Failed to queue buffers for \"\n> > -                                             << name_;\n> > -                             return ret;\n> > -                     }\n> > -             }\n> > -\n> > -             return 0;\n> > -     }\n> > -\n> > -     bool findFrameBuffer(FrameBuffer *buffer) const\n> > -     {\n> > -             auto start = external_ ? externalBuffers_->begin() : internalBuffers_.begin();\n> > -             auto end = external_ ? externalBuffers_->end() : internalBuffers_.end();\n> > -\n> > -             if (importOnly_)\n> > -                     return false;\n> > -\n> > -             if (std::find_if(start, end,\n> > -                              [buffer](std::unique_ptr<FrameBuffer> const &ref) { return ref.get() == buffer; }) != end)\n> > -                     return true;\n> > -\n> > -             return false;\n> > -     }\n> > -\n> > -private:\n> > -     /*\n> > -      * Indicates that this stream is active externally, i.e. the buffers\n> > -      * are provided by the application.\n> > -      */\n> > -     bool external_;\n> > -     /* Indicates that this stream only imports buffers, e.g. ISP input. */\n> > -     bool importOnly_;\n> > -     /* Stream name identifier. */\n> > -     std::string name_;\n> > -     /* The actual device stream. */\n> > -     std::unique_ptr<V4L2VideoDevice> dev_;\n> > -     /* Internally allocated framebuffers associated with this device stream. */\n> > -     std::vector<std::unique_ptr<FrameBuffer>> internalBuffers_;\n> > -     /* Externally allocated framebuffers associated with this device stream. */\n> > -     std::vector<std::unique_ptr<FrameBuffer>> *externalBuffers_;\n> > -};\n> > -\n> > -/*\n> > - * The following class is just a convenient (and typesafe) array of device\n> > - * streams indexed with an enum class.\n> > - */\n> >  enum class Unicam : unsigned int { Image, Embedded };\n> >  enum class Isp : unsigned int { Input, Output0, Output1, Stats };\n> >\n> > -template<typename E, std::size_t N>\n> > -class RPiDevice : public std::array<class RPiStream, N>\n> > -{\n> > -private:\n> > -     constexpr auto index(E e) const noexcept\n> > -     {\n> > -             return static_cast<std::underlying_type_t<E>>(e);\n> > -     }\n> > -public:\n> > -     RPiStream &operator[](E e)\n> > -     {\n> > -             return std::array<class RPiStream, N>::operator[](index(e));\n> > -     }\n> > -     const RPiStream &operator[](E e) const\n> > -     {\n> > -             return std::array<class RPiStream, N>::operator[](index(e));\n> > -     }\n> > -};\n> > +} /* namespace */\n> >\n> >  class RPiCameraData : public CameraData\n> >  {\n> > @@ -318,7 +163,7 @@ public:\n> >       void ispOutputDequeue(FrameBuffer *buffer);\n> >\n> >       void clearIncompleteRequests();\n> > -     void handleStreamBuffer(FrameBuffer *buffer, const RPiStream *stream);\n> > +     void handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream);\n> >       void handleState();\n> >\n> >       CameraSensor *sensor_;\n> > @@ -326,7 +171,7 @@ public:\n> >       RPiDevice<Unicam, 2> unicam_;\n> >       RPiDevice<Isp, 4> isp_;\n> >       /* The vector below is just for convenience when iterating over all streams. */\n> > -     std::vector<RPiStream *> streams_;\n> > +     std::vector<RPi::RPiStream *> streams_;\n> >       /* Buffers passed to the IPA. */\n> >       std::vector<IPABuffer> ipaBuffers_;\n> >\n> > @@ -782,7 +627,7 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)\n> >  int PipelineHandlerRPi::exportFrameBuffers(Camera *camera, Stream *stream,\n> >                                          std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n> >  {\n> > -     RPiStream *s = static_cast<RPiStream *>(stream);\n> > +     RPi::RPiStream *s = static_cast<RPi::RPiStream *>(stream);\n> >       unsigned int count = stream->configuration().bufferCount;\n> >       int ret = s->dev()->exportBuffers(count, buffers);\n> >\n> > @@ -914,14 +759,14 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)\n> >       std::unique_ptr<RPiCameraData> data = std::make_unique<RPiCameraData>(this);\n> >\n> >       /* Locate and open the unicam video streams. */\n> > -     data->unicam_[Unicam::Embedded] = RPiStream(\"Unicam Embedded\", unicam_->getEntityByName(\"unicam-embedded\"));\n> > -     data->unicam_[Unicam::Image] = RPiStream(\"Unicam Image\", unicam_->getEntityByName(\"unicam-image\"));\n> > +     data->unicam_[Unicam::Embedded] = RPi::RPiStream(\"Unicam Embedded\", unicam_->getEntityByName(\"unicam-embedded\"));\n> > +     data->unicam_[Unicam::Image] = RPi::RPiStream(\"Unicam Image\", unicam_->getEntityByName(\"unicam-image\"));\n> >\n> >       /* Tag the ISP input stream as an import stream. */\n> > -     data->isp_[Isp::Input] = RPiStream(\"ISP Input\", isp_->getEntityByName(\"bcm2835-isp0-output0\"), true);\n> > -     data->isp_[Isp::Output0] = RPiStream(\"ISP Output0\", isp_->getEntityByName(\"bcm2835-isp0-capture1\"));\n> > -     data->isp_[Isp::Output1] = RPiStream(\"ISP Output1\", isp_->getEntityByName(\"bcm2835-isp0-capture2\"));\n> > -     data->isp_[Isp::Stats] = RPiStream(\"ISP Stats\", isp_->getEntityByName(\"bcm2835-isp0-capture3\"));\n> > +     data->isp_[Isp::Input] = RPi::RPiStream(\"ISP Input\", isp_->getEntityByName(\"bcm2835-isp0-output0\"), true);\n> > +     data->isp_[Isp::Output0] = RPi::RPiStream(\"ISP Output0\", isp_->getEntityByName(\"bcm2835-isp0-capture1\"));\n> > +     data->isp_[Isp::Output1] = RPi::RPiStream(\"ISP Output1\", isp_->getEntityByName(\"bcm2835-isp0-capture2\"));\n> > +     data->isp_[Isp::Stats] = RPi::RPiStream(\"ISP Stats\", isp_->getEntityByName(\"bcm2835-isp0-capture3\"));\n> >\n> >       /* This is just for convenience so that we can easily iterate over all streams. */\n> >       for (auto &stream : data->unicam_)\n> > @@ -1070,7 +915,7 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera)\n> >        */\n> >       unsigned int maxBuffers = 0;\n> >       for (const Stream *s : camera->streams())\n> > -             if (static_cast<const RPiStream *>(s)->isExternal())\n> > +             if (static_cast<const RPi::RPiStream *>(s)->isExternal())\n> >                       maxBuffers = std::max(maxBuffers, s->configuration().bufferCount);\n> >\n> >       for (auto const stream : data->streams_) {\n> > @@ -1271,12 +1116,12 @@ done:\n> >\n> >  void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer)\n> >  {\n> > -     const RPiStream *stream = nullptr;\n> > +     const RPi::RPiStream *stream = nullptr;\n> >\n> >       if (state_ == State::Stopped)\n> >               return;\n> >\n> > -     for (RPiStream const &s : unicam_) {\n> > +     for (RPi::RPiStream const &s : unicam_) {\n> >               if (s.findFrameBuffer(buffer)) {\n> >                       stream = &s;\n> >                       break;\n> > @@ -1332,12 +1177,12 @@ void RPiCameraData::ispInputDequeue(FrameBuffer *buffer)\n> >\n> >  void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer)\n> >  {\n> > -     const RPiStream *stream = nullptr;\n> > +     const RPi::RPiStream *stream = nullptr;\n> >\n> >       if (state_ == State::Stopped)\n> >               return;\n> >\n> > -     for (RPiStream const &s : isp_) {\n> > +     for (RPi::RPiStream const &s : isp_) {\n> >               if (s.findFrameBuffer(buffer)) {\n> >                       stream = &s;\n> >                       break;\n> > @@ -1418,7 +1263,7 @@ void RPiCameraData::clearIncompleteRequests()\n> >       }\n> >  }\n> >\n> > -void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPiStream *stream)\n> > +void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream)\n> >  {\n> >       if (stream->isExternal()) {\n> >               if (!dropFrame_) {\n> > diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> > new file mode 100644\n> > index 00000000..ed4f4987\n> > --- /dev/null\n> > +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> > @@ -0,0 +1,182 @@\n> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> > +/*\n> > + * Copyright (C) 2020, Raspberry Pi (Trading) Ltd.\n> > + *\n> > + * rpi_stream.h - Raspberry Pi device stream abstraction class.\n> > + */\n> > +#ifndef __LIBCAMERA_PIPELINE_RPI_STREAM_H__\n> > +#define __LIBCAMERA_PIPELINE_RPI_STREAM_H__\n> > +\n> > +#include <queue>\n> > +#include <string>\n> > +#include <vector>\n> > +\n> > +#include \"libcamera/internal/v4l2_videodevice.h\"\n> > +#include <libcamera/stream.h>\n> > +\n> > +namespace libcamera {\n> > +\n> > +LOG_DEFINE_CATEGORY(RPISTREAM)\n> > +\n> > +namespace RPi {\n> > +\n> > +/*\n> > + * Device stream abstraction for either an internal or external stream.\n> > + * Used for both Unicam and the ISP.\n> > + */\n> > +class RPiStream : public Stream\n> > +{\n> > +public:\n> > +     RPiStream()\n> > +     {\n> > +     }\n> > +\n> > +     RPiStream(const char *name, MediaEntity *dev, bool importOnly = false)\n> > +             : external_(false), importOnly_(importOnly), name_(name),\n> > +               dev_(std::make_unique<V4L2VideoDevice>(dev))\n> > +     {\n> > +     }\n> > +\n> > +     V4L2VideoDevice *dev() const\n> > +     {\n> > +             return dev_.get();\n> > +     }\n> > +\n> > +     void setExternal(bool external)\n> > +     {\n> > +             external_ = external;\n> > +     }\n> > +\n> > +     bool isExternal() const\n> > +     {\n> > +             /*\n> > +              * Import streams cannot be external.\n> > +              *\n> > +              * RAW capture is a special case where we simply copy the RAW\n> > +              * buffer out of the request. All other buffer handling happens\n> > +              * as if the stream is internal.\n> > +              */\n> > +             return external_ && !importOnly_;\n> > +     }\n> > +\n> > +     bool isImporter() const\n> > +     {\n> > +             return importOnly_;\n> > +     }\n> > +\n> > +     void reset()\n> > +     {\n> > +             external_ = false;\n> > +             internalBuffers_.clear();\n> > +     }\n> > +\n> > +     std::string name() const\n> > +     {\n> > +             return name_;\n> > +     }\n> > +\n> > +     void setExternalBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n> > +     {\n> > +             externalBuffers_ = buffers;\n> > +     }\n> > +\n> > +     const std::vector<std::unique_ptr<FrameBuffer>> *getBuffers() const\n> > +     {\n> > +             return external_ ? externalBuffers_ : &internalBuffers_;\n> > +     }\n> > +\n> > +     void releaseBuffers()\n> > +     {\n> > +             dev_->releaseBuffers();\n> > +             if (!external_ && !importOnly_)\n> > +                     internalBuffers_.clear();\n> > +     }\n> > +\n> > +     int importBuffers(unsigned int count)\n> > +     {\n> > +             return dev_->importBuffers(count);\n> > +     }\n> > +\n> > +     int allocateBuffers(unsigned int count)\n> > +     {\n> > +             return dev_->allocateBuffers(count, &internalBuffers_);\n> > +     }\n> > +\n> > +     int queueBuffers()\n> > +     {\n> > +             if (external_)\n> > +                     return 0;\n> > +\n> > +             for (auto &b : internalBuffers_) {\n> > +                     int ret = dev_->queueBuffer(b.get());\n> > +                     if (ret) {\n> > +                             LOG(RPISTREAM, Error) << \"Failed to queue buffers for \"\n> > +                                                   << name_;\n> > +                             return ret;\n> > +                     }\n> > +             }\n> > +\n> > +             return 0;\n> > +     }\n> > +\n> > +     bool findFrameBuffer(FrameBuffer *buffer) const\n> > +     {\n> > +             auto start = external_ ? externalBuffers_->begin() : internalBuffers_.begin();\n> > +             auto end = external_ ? externalBuffers_->end() : internalBuffers_.end();\n> > +\n> > +             if (importOnly_)\n> > +                     return false;\n> > +\n> > +             if (std::find_if(start, end,\n> > +                              [buffer](std::unique_ptr<FrameBuffer> const &ref) { return ref.get() == buffer; }) != end)\n> > +                     return true;\n> > +\n> > +             return false;\n> > +     }\n> > +\n> > +private:\n> > +     /*\n> > +      * Indicates that this stream is active externally, i.e. the buffers\n> > +      * are provided by the application.\n> > +      */\n> > +     bool external_;\n> > +     /* Indicates that this stream only imports buffers, e.g. ISP input. */\n> > +     bool importOnly_;\n> > +     /* Stream name identifier. */\n> > +     std::string name_;\n> > +     /* The actual device stream. */\n> > +     std::unique_ptr<V4L2VideoDevice> dev_;\n> > +     /* Internally allocated framebuffers associated with this device stream. */\n> > +     std::vector<std::unique_ptr<FrameBuffer>> internalBuffers_;\n> > +     /* Externally allocated framebuffers associated with this device stream. */\n> > +     std::vector<std::unique_ptr<FrameBuffer>> *externalBuffers_;\n> > +};\n> > +\n> > +/*\n> > + * The following class is just a convenient (and typesafe) array of device\n> > + * streams indexed with an enum class.\n> > + */\n> > +template<typename E, std::size_t N>\n> > +class RPiDevice : public std::array<class RPiStream, N>\n> > +{\n> > +private:\n> > +     constexpr auto index(E e) const noexcept\n> > +     {\n> > +             return static_cast<std::underlying_type_t<E>>(e);\n> > +     }\n> > +public:\n> > +     RPiStream &operator[](E e)\n> > +     {\n> > +             return std::array<class RPiStream, N>::operator[](index(e));\n> > +     }\n> > +     const RPiStream &operator[](E e) const\n> > +     {\n> > +             return std::array<class RPiStream, N>::operator[](index(e));\n> > +     }\n> > +};\n> > +\n> > +} /* namespace RPi */\n> > +\n> > +} /* namespace libcamera */\n> > +\n> > +#endif /* __LIBCAMERA_PIPELINE_RPI_STREAM_H__ */\n> > --\n> > 2.25.1\n> >\n> > _______________________________________________\n> > libcamera-devel mailing list\n> > libcamera-devel@lists.libcamera.org\n> > https://lists.libcamera.org/listinfo/libcamera-devel\n>\n> --\n> Regards,\n> Niklas Söderlund","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 B06B4BD790\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 13 Jul 2020 11:32:46 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3DD33605B4;\n\tMon, 13 Jul 2020 13:32:46 +0200 (CEST)","from mail-lf1-x12d.google.com (mail-lf1-x12d.google.com\n\t[IPv6:2a00:1450:4864:20::12d])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E0E58603A4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 13 Jul 2020 13:32:43 +0200 (CEST)","by mail-lf1-x12d.google.com with SMTP id t9so8779681lfl.5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 13 Jul 2020 04:32:43 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"tzJVkCdf\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc:content-transfer-encoding;\n\tbh=XeHBraGw3aUH2AAP5q/l/8icPdc2J+/99lFsgO+aAI4=;\n\tb=tzJVkCdf/+kxxgyfPtvaDecFSKPXaipJXmmMbKRnZM+AlozHISimEvU0jCpNW2URCZ\n\tBuMXd+vkFFqz/4QKclr9I+XSTaZw41TsPCZLMUJ/1F3/CN96ZQjG5eZXqpfd+Acc4Wa4\n\t9sAZAdGjEazg21VDkar4Yxng+fWG/BCsJUoNbTvhI1R737SGVI+MROPIl7xZIjEPW+jZ\n\to366TresPMVH7NiGQH5+Dth5vDAU6w4H49P1OW7TsfTAodrUjoJIuF5czVyisQaK9zMs\n\tSJoxYWFk3VpPmLfz3t4FzjS0iay1w5Ocxjvq0jQU5P6EciYuJbemXeBrcV7kO3QHg9ed\n\tqV7w==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc:content-transfer-encoding;\n\tbh=XeHBraGw3aUH2AAP5q/l/8icPdc2J+/99lFsgO+aAI4=;\n\tb=ozwv7xNPa5s/84sEQ5aXqTflb/M5nvAYYHpsNDZipdu0dV9gbocN0yvO1Z5OmWv0Ph\n\tyJaUpa2rj17lX6EAqGa1xnU+RLTHT2i+/Kdi3ffZtsQ6UJxgWNf0HQxBi7/79G0WEYA/\n\tL+ntRZKDlVJNRVDQONP/Bg5AoBntgxFJTq75cKe2E4aLB7fYCdqlH0RhcupaK2u/nDaC\n\tuerslPkLwBFGJwZCJl3dtDlGSDv7WvLPQ0JX5OKHp/uunmalzUNyJaEZ0miyliPnyqMi\n\tFoJ0tM9wQb0BIm7uIOQ01WH6T3B44j9swUFDPMatuhDa8ZYDg4IDd0Ry5kabEGKiAFSi\n\tmYYA==","X-Gm-Message-State":"AOAM532KE+FYb1a3NP2uzzU3nhBwUhz0LDzun3JODaQ2c3N6TZxSOB+X\n\t6RoFnldHWhUhFbhZqt4YnH8KFO2VAzGtXNKM3E8yVQ==","X-Google-Smtp-Source":"ABdhPJwy4MGWhaWCb7pKSxFua3rvNE15RQu5i7Up1XmnHVqOIMyE/1vA24X54zjuN8j3jA6IlurRTQ5OZWjKOFeHhr0=","X-Received":"by 2002:a19:f20a:: with SMTP id\n\tq10mr53141373lfh.89.1594639963053; \n\tMon, 13 Jul 2020 04:32:43 -0700 (PDT)","MIME-Version":"1.0","References":"<20200713084727.232422-1-naush@raspberrypi.com>\n\t<20200713084727.232422-2-naush@raspberrypi.com>\n\t<20200713112637.GC2866302@oden.dyn.berto.se>","In-Reply-To":"<20200713112637.GC2866302@oden.dyn.berto.se>","From":"Naushir Patuck <naush@raspberrypi.com>","Date":"Mon, 13 Jul 2020 12:32:25 +0100","Message-ID":"<CAEmqJPo3MX5M4xVJ-Xt13hYUURZU+j5avwkEB4TZd78prUfstA@mail.gmail.com>","To":"=?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Subject":"Re: [libcamera-devel] [PATCH 1/9] libcamera: pipeline: raspberrypi:\n\tMove RPiStream into a separate header","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":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]