[{"id":648,"web_url":"https://patchwork.libcamera.org/comment/648/","msgid":"<20190128000910.GD5154@pendragon.ideasonboard.com>","date":"2019-01-28T00:09:10","subject":"Re: [libcamera-devel] [PATCH v3 5/6] libcamera: pipeline: extend\n\tpipelines to support stream configuration","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Niklas,\n\nThank you for the patch.\n\nOn Sun, Jan 27, 2019 at 01:22:07AM +0100, Niklas Söderlund wrote:\n> All streams which are to be used for capture needs to be configured at\n\ns/needs/need/\n\n> the same time. This allows the pipeline handler to take any dependences\n\ns/dependences/dependencies/\n\n> between the different streams and there configuration into account when\n\ns/there configuration/their configurations/\n\n> setting up the hardware.\n> \n> Extend the pipeline API and all pipeline implementations with two new\n> functions, one to read the configuration and one to update it. Both\n> functions operate on a group of streams which the pipeline handler\n> should consider when performing the operations.\n\nI don't think we should have a function to read the current\nconfiguration, and if we did, it shouldn't be virtual, but implemented\nin PipelineHandler using a cache.\n\nWhat we need is a function for a pipeline handler to return a default\nconfiguration for a set of streams, in order for applications not to\nhave to create a configuration from scratch but start from a known to\nwork (and recommended) config.\n\n> In the current implemented pipelines this is rather easy as they only\n> have one stream each per camera. Furthermore as there is yet no way for\n> the pipeline handlers to interact with the hardware all they do is log\n> that the format have been read or updated. Future work based on more\n> components are needed to make the pipelines actually interact with the\n> hardware.\n> \n> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> ---\n>  src/libcamera/include/pipeline_handler.h |  8 ++++++\n>  src/libcamera/pipeline/ipu3/ipu3.cpp     | 32 ++++++++++++++++++++++\n>  src/libcamera/pipeline/uvcvideo.cpp      | 35 ++++++++++++++++++++++++\n>  src/libcamera/pipeline/vimc.cpp          | 35 ++++++++++++++++++++++++\n>  src/libcamera/pipeline_handler.cpp       | 34 +++++++++++++++++++++++\n>  5 files changed, 144 insertions(+)\n> \n> diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h\n> index ca77a40b96e69b66..c19eb9b73ede8720 100644\n> --- a/src/libcamera/include/pipeline_handler.h\n> +++ b/src/libcamera/include/pipeline_handler.h\n> @@ -17,6 +17,8 @@ namespace libcamera {\n>  class CameraManager;\n>  class DeviceEnumerator;\n>  class MediaDevice;\n> +class Stream;\n> +class StreamConfiguration;\n>  \n>  class Camera;\n>  class CameraData\n> @@ -38,6 +40,12 @@ public:\n>  \tPipelineHandler(CameraManager *manager);\n>  \tvirtual ~PipelineHandler();\n>  \n> +\tvirtual std::map<unsigned int, StreamConfiguration>\n> +\tstreamConfiguration(const Camera *camera,\n> +\t\t\t    const std::vector<Stream> &streams) const = 0;\n> +\tvirtual int configureStreams(const Camera *camera,\n\nEven if you don't need to modify the state of the Camera object now, you\nmay need that later. Beside, this method is called by the Camera class\nfrom a non-cost instance, so that won't be a problem.\n\n> +\t\t\t\t     std::map<unsigned int, StreamConfiguration> &config) = 0;\n> +\n>  \tvirtual bool match(DeviceEnumerator *enumerator) = 0;\n>  \n>  protected:\n> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> index dbb2a89163c36cbc..ff4d73f947a683ca 100644\n> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> @@ -28,6 +28,12 @@ public:\n>  \tPipelineHandlerIPU3(CameraManager *manager);\n>  \t~PipelineHandlerIPU3();\n>  \n> +\tstd::map<unsigned int, StreamConfiguration>\n> +\tstreamConfiguration(const Camera *camera,\n> +\t\t\t    const std::vector<Stream> &streams) const;\n> +\tint configureStreams(const Camera *camera,\n> +\t\t\t     std::map<unsigned int, StreamConfiguration> &config);\n> +\n>  \tbool match(DeviceEnumerator *enumerator);\n>  \n>  private:\n> @@ -61,6 +67,32 @@ PipelineHandlerIPU3::~PipelineHandlerIPU3()\n>  \t\timgu_->release();\n>  }\n>  \n> +std::map<unsigned int, StreamConfiguration>\n> +PipelineHandlerIPU3::streamConfiguration(const Camera *camera,\n> +\t\t\t\t\t const std::vector<Stream> &streams) const\n> +{\n> +\tstd::map<unsigned int, StreamConfiguration> configs;\n> +\n> +\tStreamConfiguration config;\n> +\n> +\tLOG(IPU3, Info) << \"TODO: Fetch stream configuration\";\n> +\n> +\tconfigs[0] = config;\n> +\n> +\treturn configs;\n> +}\n> +\n> +int PipelineHandlerIPU3::configureStreams(const Camera *camera,\n> +\t\t\t\t\t  std::map<unsigned int, StreamConfiguration> &config)\n> +{\n> +\tStreamConfiguration *cfg = &config[0];\n> +\n> +\tLOG(IPU3, Info) << \"TODO: Configure the camera for resolution \" <<\n> +\t\tcfg->width << \"x\" << cfg->height;\n> +\n> +\treturn 0;\n> +}\n> +\n>  bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)\n>  {\n>  \tDeviceMatch cio2_dm(\"ipu3-cio2\");\n> diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp\n> index bc4a8d7236be589d..bba4655a0a26b622 100644\n> --- a/src/libcamera/pipeline/uvcvideo.cpp\n> +++ b/src/libcamera/pipeline/uvcvideo.cpp\n> @@ -9,18 +9,27 @@\n>  #include <libcamera/stream.h>\n>  \n>  #include \"device_enumerator.h\"\n> +#include \"log.h\"\n>  #include \"media_device.h\"\n>  #include \"pipeline_handler.h\"\n>  #include \"v4l2_device.h\"\n>  \n>  namespace libcamera {\n>  \n> +LOG_DEFINE_CATEGORY(UVC)\n> +\n>  class PipelineHandlerUVC : public PipelineHandler\n>  {\n>  public:\n>  \tPipelineHandlerUVC(CameraManager *manager);\n>  \t~PipelineHandlerUVC();\n>  \n> +\tstd::map<unsigned int, StreamConfiguration>\n> +\tstreamConfiguration(const Camera *camera,\n> +\t\t\t    const std::vector<Stream> &streams) const;\n> +\tint configureStreams(const Camera *camera,\n> +\t\t\t     std::map<unsigned int, StreamConfiguration> &config);\n> +\n>  \tbool match(DeviceEnumerator *enumerator);\n>  \n>  private:\n> @@ -42,6 +51,32 @@ PipelineHandlerUVC::~PipelineHandlerUVC()\n>  \t\tmedia_->release();\n>  }\n>  \n> +std::map<unsigned int, StreamConfiguration>\n> +PipelineHandlerUVC::streamConfiguration(const Camera *camera,\n> +\t\t\t\t\tconst std::vector<Stream> &streams) const\n> +{\n> +\tstd::map<unsigned int, StreamConfiguration> configs;\n> +\n> +\tStreamConfiguration config;\n> +\n> +\tLOG(UVC, Info) << \"TODO: Fetch stream configuration\";\n> +\n> +\tconfigs[0] = config;\n> +\n> +\treturn configs;\n> +}\n> +\n> +int PipelineHandlerUVC::configureStreams(const Camera *camera,\n> +\t\t\t\t\t std::map<unsigned int, StreamConfiguration> &config)\n> +{\n> +\tStreamConfiguration *cfg = &config[0];\n> +\n> +\tLOG(UVC, Info) << \"TODO: Configure the camera for resolution \" <<\n> +\t\tcfg->width << \"x\" << cfg->height;\n> +\n> +\treturn 0;\n> +}\n> +\n>  bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n>  {\n>  \tDeviceMatch dm(\"uvcvideo\");\n> diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp\n> index c426a953aea1b3dd..c9810a8e192ac68b 100644\n> --- a/src/libcamera/pipeline/vimc.cpp\n> +++ b/src/libcamera/pipeline/vimc.cpp\n> @@ -9,17 +9,26 @@\n>  #include <libcamera/stream.h>\n>  \n>  #include \"device_enumerator.h\"\n> +#include \"log.h\"\n>  #include \"media_device.h\"\n>  #include \"pipeline_handler.h\"\n>  \n>  namespace libcamera {\n>  \n> +LOG_DEFINE_CATEGORY(VIMC)\n> +\n>  class PipeHandlerVimc : public PipelineHandler\n>  {\n>  public:\n>  \tPipeHandlerVimc(CameraManager *manager);\n>  \t~PipeHandlerVimc();\n>  \n> +\tstd::map<unsigned int, StreamConfiguration>\n> +\tstreamConfiguration(const Camera *camera,\n> +\t\t\t    const std::vector<Stream> &streams) const;\n> +\tint configureStreams(const Camera *camera,\n> +\t\t\t     std::map<unsigned int, StreamConfiguration> &config);\n> +\n>  \tbool match(DeviceEnumerator *enumerator);\n>  \n>  private:\n> @@ -37,6 +46,32 @@ PipeHandlerVimc::~PipeHandlerVimc()\n>  \t\tmedia_->release();\n>  }\n>  \n> +std::map<unsigned int, StreamConfiguration>\n> +PipeHandlerVimc::streamConfiguration(const Camera *camera,\n> +\t\t\t\t     const std::vector<Stream> &streams) const\n> +{\n> +\tstd::map<unsigned int, StreamConfiguration> configs;\n> +\n> +\tStreamConfiguration config;\n> +\n> +\tLOG(VIMC, Info) << \"TODO: Fetch stream configuration\";\n> +\n> +\tconfigs[0] = config;\n> +\n> +\treturn configs;\n> +}\n> +\n> +int PipeHandlerVimc::configureStreams(const Camera *camera,\n> +\t\t\t\t      std::map<unsigned int, StreamConfiguration> &config)\n> +{\n> +\tStreamConfiguration *cfg = &config[0];\n> +\n> +\tLOG(VIMC, Info) << \"TODO: Configure the camera for resolution \" <<\n> +\t\tcfg->width << \"x\" << cfg->height;\n> +\n> +\treturn 0;\n> +}\n> +\n>  bool PipeHandlerVimc::match(DeviceEnumerator *enumerator)\n>  {\n>  \tDeviceMatch dm(\"vimc\");\n> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp\n> index 1c8640799f714686..ee6d80908f67d564 100644\n> --- a/src/libcamera/pipeline_handler.cpp\n> +++ b/src/libcamera/pipeline_handler.cpp\n> @@ -75,6 +75,40 @@ PipelineHandler::~PipelineHandler()\n>  {\n>  };\n>  \n> +\n> +/**\n> + * \\fn PipelineHandler::streamConfiguration(const Camera *camera, * const std::vector<Stream> &streams)\n\nYou don't need to specify the function parameters when the function\nisn't overloaded.\n\n> + * \\brief Retrieve a group of stream configurations for a specified camera\n> + * \\param[in] camera The camera to fetch the configuration from\n> + * \\param[in] streams An array of streams to fetch information about\n> + *\n> + * Retrieve the species camera's configuration for a specified group of streams.\n> + * The caller shall populate the \\a streams array with the streams it wish to\n> + * fetch the configuration from. The map of stream IDs and configuration\n> + * returned can then be examined by the caller to learn about the parameters for\n> + * the specified streams.\n> + *\n> + * The intended companion to this is \\a configureStreams() which can be used to\n> + * change the group of streams parameters.\n> + *\n> + * \\return A map of successfully retrieved stream IDs and configurations or an\n> + * empty map on error.\n> + */\n> +\n> +/**\n> + * \\fn PipelineHandler::configureStreams(const Camera *camera, std::map<unsigned int, StreamConfiguration> &config)\n> + * \\brief Configure a group of streams for capture\n> + * \\param[in] camera The camera to apply the configuration to\n\nYou could simply say \"The camera to configure\".\n\n> + * \\param[in] config A map of stream configurations to apply\n> + *\n> + * Configure the specified group of streams for \\a camera according to the\n> + * configuration specified in \\a configs. The intended caller of this interface\n> + * is the Camera class which will receive configuration to apply from the\n> + * application.\n> + *\n> + * \\return 0 on success or a negative error code on error.\n> + */\n> +\n>  /**\n>   * \\fn PipelineHandler::match(DeviceEnumerator *enumerator)\n>   * \\brief Match media devices and create camera instances","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9183A60C78\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 28 Jan 2019 01:09:14 +0100 (CET)","from pendragon.ideasonboard.com (85-76-73-155-nat.elisa-mobile.fi\n\t[85.76.73.155])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E5B5085;\n\tMon, 28 Jan 2019 01:09:12 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1548634154;\n\tbh=cYCXnxmlI4xQddw4SoZktPhcfsY2ruGPLvOhu/i5300=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=tKXJbgQ/F4//Xns9mx7O/porATPvXniynYw14dsPRkSNkdjY/4wmHmYCyiqpCzX11\n\tfsVHf29BxCQOA78ueimors+/k23OYIHqygH9aFEVUecDTpblT4/pQEdluqAsSFdw4k\n\taoeNv/SxPTYz1p2RtGrFtnG8W1awxmEBQ/gaM128=","Date":"Mon, 28 Jan 2019 02:09:10 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190128000910.GD5154@pendragon.ideasonboard.com>","References":"<20190127002208.18913-1-niklas.soderlund@ragnatech.se>\n\t<20190127002208.18913-6-niklas.soderlund@ragnatech.se>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20190127002208.18913-6-niklas.soderlund@ragnatech.se>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH v3 5/6] libcamera: pipeline: extend\n\tpipelines to support stream configuration","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","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>","X-List-Received-Date":"Mon, 28 Jan 2019 00:09:14 -0000"}},{"id":653,"web_url":"https://patchwork.libcamera.org/comment/653/","msgid":"<20190128113018.nirtpj4ksnipkitk@uno.localdomain>","date":"2019-01-28T11:30:19","subject":"Re: [libcamera-devel] [PATCH v3 5/6] libcamera: pipeline: extend\n\tpipelines to support stream configuration","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Niklas, Laurent\n\nOn Mon, Jan 28, 2019 at 02:09:10AM +0200, Laurent Pinchart wrote:\n> Hi Niklas,\n>\n> Thank you for the patch.\n>\n> On Sun, Jan 27, 2019 at 01:22:07AM +0100, Niklas Söderlund wrote:\n> > All streams which are to be used for capture needs to be configured at\n>\n> s/needs/need/\n>\n> > the same time. This allows the pipeline handler to take any dependences\n>\n> s/dependences/dependencies/\n>\n> > between the different streams and there configuration into account when\n>\n> s/there configuration/their configurations/\n>\n> > setting up the hardware.\n> >\n> > Extend the pipeline API and all pipeline implementations with two new\n> > functions, one to read the configuration and one to update it. Both\n> > functions operate on a group of streams which the pipeline handler\n> > should consider when performing the operations.\n>\n> I don't think we should have a function to read the current\n> configuration, and if we did, it shouldn't be virtual, but implemented\n> in PipelineHandler using a cache.\n>\n> What we need is a function for a pipeline handler to return a default\n> configuration for a set of streams, in order for applications not to\n> have to create a configuration from scratch but start from a known to\n> work (and recommended) config.\n>\n\nI'm sure this has been considered, and I even re-call we discussed\nthat possibly, but I fail to remember why StreamConfigurations should\nbe associated with IDs and not be part of the Stream itself.\n\nI would go futher, and ask why Streams are not created with a default\nconfiguration embedded, instead of asking for a default configuration\nwith streamConfiguration().\n\nI recall the problem was that not all streams could be part of a\nconfigureStreams() request, and that's why we pass configurations+id.\nIsn't enough to include in the requests a reference to the Streams the\napplication actually wants to setup?\n\nThanks\n  j\n\n\n> > In the current implemented pipelines this is rather easy as they only\n> > have one stream each per camera. Furthermore as there is yet no way for\n> > the pipeline handlers to interact with the hardware all they do is log\n> > that the format have been read or updated. Future work based on more\n> > components are needed to make the pipelines actually interact with the\n> > hardware.\n> >\n> > Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> > ---\n> >  src/libcamera/include/pipeline_handler.h |  8 ++++++\n> >  src/libcamera/pipeline/ipu3/ipu3.cpp     | 32 ++++++++++++++++++++++\n> >  src/libcamera/pipeline/uvcvideo.cpp      | 35 ++++++++++++++++++++++++\n> >  src/libcamera/pipeline/vimc.cpp          | 35 ++++++++++++++++++++++++\n> >  src/libcamera/pipeline_handler.cpp       | 34 +++++++++++++++++++++++\n> >  5 files changed, 144 insertions(+)\n> >\n> > diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h\n> > index ca77a40b96e69b66..c19eb9b73ede8720 100644\n> > --- a/src/libcamera/include/pipeline_handler.h\n> > +++ b/src/libcamera/include/pipeline_handler.h\n> > @@ -17,6 +17,8 @@ namespace libcamera {\n> >  class CameraManager;\n> >  class DeviceEnumerator;\n> >  class MediaDevice;\n> > +class Stream;\n> > +class StreamConfiguration;\n> >\n> >  class Camera;\n> >  class CameraData\n> > @@ -38,6 +40,12 @@ public:\n> >  \tPipelineHandler(CameraManager *manager);\n> >  \tvirtual ~PipelineHandler();\n> >\n> > +\tvirtual std::map<unsigned int, StreamConfiguration>\n> > +\tstreamConfiguration(const Camera *camera,\n> > +\t\t\t    const std::vector<Stream> &streams) const = 0;\n> > +\tvirtual int configureStreams(const Camera *camera,\n>\n> Even if you don't need to modify the state of the Camera object now, you\n> may need that later. Beside, this method is called by the Camera class\n> from a non-cost instance, so that won't be a problem.\n>\n> > +\t\t\t\t     std::map<unsigned int, StreamConfiguration> &config) = 0;\n> > +\n> >  \tvirtual bool match(DeviceEnumerator *enumerator) = 0;\n> >\n> >  protected:\n> > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > index dbb2a89163c36cbc..ff4d73f947a683ca 100644\n> > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > @@ -28,6 +28,12 @@ public:\n> >  \tPipelineHandlerIPU3(CameraManager *manager);\n> >  \t~PipelineHandlerIPU3();\n> >\n> > +\tstd::map<unsigned int, StreamConfiguration>\n> > +\tstreamConfiguration(const Camera *camera,\n> > +\t\t\t    const std::vector<Stream> &streams) const;\n> > +\tint configureStreams(const Camera *camera,\n> > +\t\t\t     std::map<unsigned int, StreamConfiguration> &config);\n> > +\n> >  \tbool match(DeviceEnumerator *enumerator);\n> >\n> >  private:\n> > @@ -61,6 +67,32 @@ PipelineHandlerIPU3::~PipelineHandlerIPU3()\n> >  \t\timgu_->release();\n> >  }\n> >\n> > +std::map<unsigned int, StreamConfiguration>\n> > +PipelineHandlerIPU3::streamConfiguration(const Camera *camera,\n> > +\t\t\t\t\t const std::vector<Stream> &streams) const\n> > +{\n> > +\tstd::map<unsigned int, StreamConfiguration> configs;\n> > +\n> > +\tStreamConfiguration config;\n> > +\n> > +\tLOG(IPU3, Info) << \"TODO: Fetch stream configuration\";\n> > +\n> > +\tconfigs[0] = config;\n> > +\n> > +\treturn configs;\n> > +}\n> > +\n> > +int PipelineHandlerIPU3::configureStreams(const Camera *camera,\n> > +\t\t\t\t\t  std::map<unsigned int, StreamConfiguration> &config)\n> > +{\n> > +\tStreamConfiguration *cfg = &config[0];\n> > +\n> > +\tLOG(IPU3, Info) << \"TODO: Configure the camera for resolution \" <<\n> > +\t\tcfg->width << \"x\" << cfg->height;\n> > +\n> > +\treturn 0;\n> > +}\n> > +\n> >  bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)\n> >  {\n> >  \tDeviceMatch cio2_dm(\"ipu3-cio2\");\n> > diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp\n> > index bc4a8d7236be589d..bba4655a0a26b622 100644\n> > --- a/src/libcamera/pipeline/uvcvideo.cpp\n> > +++ b/src/libcamera/pipeline/uvcvideo.cpp\n> > @@ -9,18 +9,27 @@\n> >  #include <libcamera/stream.h>\n> >\n> >  #include \"device_enumerator.h\"\n> > +#include \"log.h\"\n> >  #include \"media_device.h\"\n> >  #include \"pipeline_handler.h\"\n> >  #include \"v4l2_device.h\"\n> >\n> >  namespace libcamera {\n> >\n> > +LOG_DEFINE_CATEGORY(UVC)\n> > +\n> >  class PipelineHandlerUVC : public PipelineHandler\n> >  {\n> >  public:\n> >  \tPipelineHandlerUVC(CameraManager *manager);\n> >  \t~PipelineHandlerUVC();\n> >\n> > +\tstd::map<unsigned int, StreamConfiguration>\n> > +\tstreamConfiguration(const Camera *camera,\n> > +\t\t\t    const std::vector<Stream> &streams) const;\n> > +\tint configureStreams(const Camera *camera,\n> > +\t\t\t     std::map<unsigned int, StreamConfiguration> &config);\n> > +\n> >  \tbool match(DeviceEnumerator *enumerator);\n> >\n> >  private:\n> > @@ -42,6 +51,32 @@ PipelineHandlerUVC::~PipelineHandlerUVC()\n> >  \t\tmedia_->release();\n> >  }\n> >\n> > +std::map<unsigned int, StreamConfiguration>\n> > +PipelineHandlerUVC::streamConfiguration(const Camera *camera,\n> > +\t\t\t\t\tconst std::vector<Stream> &streams) const\n> > +{\n> > +\tstd::map<unsigned int, StreamConfiguration> configs;\n> > +\n> > +\tStreamConfiguration config;\n> > +\n> > +\tLOG(UVC, Info) << \"TODO: Fetch stream configuration\";\n> > +\n> > +\tconfigs[0] = config;\n> > +\n> > +\treturn configs;\n> > +}\n> > +\n> > +int PipelineHandlerUVC::configureStreams(const Camera *camera,\n> > +\t\t\t\t\t std::map<unsigned int, StreamConfiguration> &config)\n> > +{\n> > +\tStreamConfiguration *cfg = &config[0];\n> > +\n> > +\tLOG(UVC, Info) << \"TODO: Configure the camera for resolution \" <<\n> > +\t\tcfg->width << \"x\" << cfg->height;\n> > +\n> > +\treturn 0;\n> > +}\n> > +\n> >  bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n> >  {\n> >  \tDeviceMatch dm(\"uvcvideo\");\n> > diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp\n> > index c426a953aea1b3dd..c9810a8e192ac68b 100644\n> > --- a/src/libcamera/pipeline/vimc.cpp\n> > +++ b/src/libcamera/pipeline/vimc.cpp\n> > @@ -9,17 +9,26 @@\n> >  #include <libcamera/stream.h>\n> >\n> >  #include \"device_enumerator.h\"\n> > +#include \"log.h\"\n> >  #include \"media_device.h\"\n> >  #include \"pipeline_handler.h\"\n> >\n> >  namespace libcamera {\n> >\n> > +LOG_DEFINE_CATEGORY(VIMC)\n> > +\n> >  class PipeHandlerVimc : public PipelineHandler\n> >  {\n> >  public:\n> >  \tPipeHandlerVimc(CameraManager *manager);\n> >  \t~PipeHandlerVimc();\n> >\n> > +\tstd::map<unsigned int, StreamConfiguration>\n> > +\tstreamConfiguration(const Camera *camera,\n> > +\t\t\t    const std::vector<Stream> &streams) const;\n> > +\tint configureStreams(const Camera *camera,\n> > +\t\t\t     std::map<unsigned int, StreamConfiguration> &config);\n> > +\n> >  \tbool match(DeviceEnumerator *enumerator);\n> >\n> >  private:\n> > @@ -37,6 +46,32 @@ PipeHandlerVimc::~PipeHandlerVimc()\n> >  \t\tmedia_->release();\n> >  }\n> >\n> > +std::map<unsigned int, StreamConfiguration>\n> > +PipeHandlerVimc::streamConfiguration(const Camera *camera,\n> > +\t\t\t\t     const std::vector<Stream> &streams) const\n> > +{\n> > +\tstd::map<unsigned int, StreamConfiguration> configs;\n> > +\n> > +\tStreamConfiguration config;\n> > +\n> > +\tLOG(VIMC, Info) << \"TODO: Fetch stream configuration\";\n> > +\n> > +\tconfigs[0] = config;\n> > +\n> > +\treturn configs;\n> > +}\n> > +\n> > +int PipeHandlerVimc::configureStreams(const Camera *camera,\n> > +\t\t\t\t      std::map<unsigned int, StreamConfiguration> &config)\n> > +{\n> > +\tStreamConfiguration *cfg = &config[0];\n> > +\n> > +\tLOG(VIMC, Info) << \"TODO: Configure the camera for resolution \" <<\n> > +\t\tcfg->width << \"x\" << cfg->height;\n> > +\n> > +\treturn 0;\n> > +}\n> > +\n> >  bool PipeHandlerVimc::match(DeviceEnumerator *enumerator)\n> >  {\n> >  \tDeviceMatch dm(\"vimc\");\n> > diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp\n> > index 1c8640799f714686..ee6d80908f67d564 100644\n> > --- a/src/libcamera/pipeline_handler.cpp\n> > +++ b/src/libcamera/pipeline_handler.cpp\n> > @@ -75,6 +75,40 @@ PipelineHandler::~PipelineHandler()\n> >  {\n> >  };\n> >\n> > +\n> > +/**\n> > + * \\fn PipelineHandler::streamConfiguration(const Camera *camera, * const std::vector<Stream> &streams)\n>\n> You don't need to specify the function parameters when the function\n> isn't overloaded.\n>\n> > + * \\brief Retrieve a group of stream configurations for a specified camera\n> > + * \\param[in] camera The camera to fetch the configuration from\n> > + * \\param[in] streams An array of streams to fetch information about\n> > + *\n> > + * Retrieve the species camera's configuration for a specified group of streams.\n> > + * The caller shall populate the \\a streams array with the streams it wish to\n> > + * fetch the configuration from. The map of stream IDs and configuration\n> > + * returned can then be examined by the caller to learn about the parameters for\n> > + * the specified streams.\n> > + *\n> > + * The intended companion to this is \\a configureStreams() which can be used to\n> > + * change the group of streams parameters.\n> > + *\n> > + * \\return A map of successfully retrieved stream IDs and configurations or an\n> > + * empty map on error.\n> > + */\n> > +\n> > +/**\n> > + * \\fn PipelineHandler::configureStreams(const Camera *camera, std::map<unsigned int, StreamConfiguration> &config)\n> > + * \\brief Configure a group of streams for capture\n> > + * \\param[in] camera The camera to apply the configuration to\n>\n> You could simply say \"The camera to configure\".\n>\n> > + * \\param[in] config A map of stream configurations to apply\n> > + *\n> > + * Configure the specified group of streams for \\a camera according to the\n> > + * configuration specified in \\a configs. The intended caller of this interface\n> > + * is the Camera class which will receive configuration to apply from the\n> > + * application.\n> > + *\n> > + * \\return 0 on success or a negative error code on error.\n> > + */\n> > +\n> >  /**\n> >   * \\fn PipelineHandler::match(DeviceEnumerator *enumerator)\n> >   * \\brief Match media devices and create camera instances\n>\n> --\n> Regards,\n>\n> Laurent Pinchart\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net\n\t[217.70.183.195])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9657B60C6A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 28 Jan 2019 12:30:10 +0100 (CET)","from uno.localdomain (2-224-242-101.ip172.fastwebnet.it\n\t[2.224.242.101]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay3-d.mail.gandi.net (Postfix) with ESMTPSA id C396160014;\n\tMon, 28 Jan 2019 11:30:09 +0000 (UTC)"],"X-Originating-IP":"2.224.242.101","Date":"Mon, 28 Jan 2019 12:30:19 +0100","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>,\n\tlibcamera-devel@lists.libcamera.org","Message-ID":"<20190128113018.nirtpj4ksnipkitk@uno.localdomain>","References":"<20190127002208.18913-1-niklas.soderlund@ragnatech.se>\n\t<20190127002208.18913-6-niklas.soderlund@ragnatech.se>\n\t<20190128000910.GD5154@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha256;\n\tprotocol=\"application/pgp-signature\"; boundary=\"7ycn2mz7ppxqkxx5\"","Content-Disposition":"inline","In-Reply-To":"<20190128000910.GD5154@pendragon.ideasonboard.com>","User-Agent":"NeoMutt/20180716","Subject":"Re: [libcamera-devel] [PATCH v3 5/6] libcamera: pipeline: extend\n\tpipelines to support stream configuration","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","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>","X-List-Received-Date":"Mon, 28 Jan 2019 11:30:10 -0000"}},{"id":663,"web_url":"https://patchwork.libcamera.org/comment/663/","msgid":"<20190128215746.GC4332@pendragon.ideasonboard.com>","date":"2019-01-28T21:57:46","subject":"Re: [libcamera-devel] [PATCH v3 5/6] libcamera: pipeline: extend\n\tpipelines to support stream configuration","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn Mon, Jan 28, 2019 at 12:30:19PM +0100, Jacopo Mondi wrote:\n> On Mon, Jan 28, 2019 at 02:09:10AM +0200, Laurent Pinchart wrote:\n> > On Sun, Jan 27, 2019 at 01:22:07AM +0100, Niklas Söderlund wrote:\n> > > All streams which are to be used for capture needs to be configured at\n> >\n> > s/needs/need/\n> >\n> > > the same time. This allows the pipeline handler to take any dependences\n> >\n> > s/dependences/dependencies/\n> >\n> > > between the different streams and there configuration into account when\n> >\n> > s/there configuration/their configurations/\n> >\n> > > setting up the hardware.\n> > >\n> > > Extend the pipeline API and all pipeline implementations with two new\n> > > functions, one to read the configuration and one to update it. Both\n> > > functions operate on a group of streams which the pipeline handler\n> > > should consider when performing the operations.\n> >\n> > I don't think we should have a function to read the current\n> > configuration, and if we did, it shouldn't be virtual, but implemented\n> > in PipelineHandler using a cache.\n> >\n> > What we need is a function for a pipeline handler to return a default\n> > configuration for a set of streams, in order for applications not to\n> > have to create a configuration from scratch but start from a known to\n> > work (and recommended) config.\n> \n> I'm sure this has been considered, and I even re-call we discussed\n> that possibly, but I fail to remember why StreamConfigurations should\n> be associated with IDs and not be part of the Stream itself.\n> \n> I would go futher, and ask why Streams are not created with a default\n> configuration embedded, instead of asking for a default configuration\n> with streamConfiguration().\n> \n> I recall the problem was that not all streams could be part of a\n> configureStreams() request, and that's why we pass configurations+id.\n> Isn't enough to include in the requests a reference to the Streams the\n> application actually wants to setup?\n\nOne issue we need to solve is to provide a default configuration for a\nsubset of streams. This isn't equivalent to adding default\nconfigurations for each stream in the subset. For instance, when you\nhave shared resources, you need to assign them to streams in the best\npossible way for the subset of streams that the application wants to\nuse. A global default for each stream wouldn't work in this case.\n\n> > > In the current implemented pipelines this is rather easy as they only\n> > > have one stream each per camera. Furthermore as there is yet no way for\n> > > the pipeline handlers to interact with the hardware all they do is log\n> > > that the format have been read or updated. Future work based on more\n> > > components are needed to make the pipelines actually interact with the\n> > > hardware.\n> > >\n> > > Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> > > ---\n> > >  src/libcamera/include/pipeline_handler.h |  8 ++++++\n> > >  src/libcamera/pipeline/ipu3/ipu3.cpp     | 32 ++++++++++++++++++++++\n> > >  src/libcamera/pipeline/uvcvideo.cpp      | 35 ++++++++++++++++++++++++\n> > >  src/libcamera/pipeline/vimc.cpp          | 35 ++++++++++++++++++++++++\n> > >  src/libcamera/pipeline_handler.cpp       | 34 +++++++++++++++++++++++\n> > >  5 files changed, 144 insertions(+)\n> > >\n> > > diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h\n> > > index ca77a40b96e69b66..c19eb9b73ede8720 100644\n> > > --- a/src/libcamera/include/pipeline_handler.h\n> > > +++ b/src/libcamera/include/pipeline_handler.h\n> > > @@ -17,6 +17,8 @@ namespace libcamera {\n> > >  class CameraManager;\n> > >  class DeviceEnumerator;\n> > >  class MediaDevice;\n> > > +class Stream;\n> > > +class StreamConfiguration;\n> > >\n> > >  class Camera;\n> > >  class CameraData\n> > > @@ -38,6 +40,12 @@ public:\n> > >  \tPipelineHandler(CameraManager *manager);\n> > >  \tvirtual ~PipelineHandler();\n> > >\n> > > +\tvirtual std::map<unsigned int, StreamConfiguration>\n> > > +\tstreamConfiguration(const Camera *camera,\n> > > +\t\t\t    const std::vector<Stream> &streams) const = 0;\n> > > +\tvirtual int configureStreams(const Camera *camera,\n> >\n> > Even if you don't need to modify the state of the Camera object now, you\n> > may need that later. Beside, this method is called by the Camera class\n> > from a non-cost instance, so that won't be a problem.\n> >\n> > > +\t\t\t\t     std::map<unsigned int, StreamConfiguration> &config) = 0;\n> > > +\n> > >  \tvirtual bool match(DeviceEnumerator *enumerator) = 0;\n> > >\n> > >  protected:\n> > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > index dbb2a89163c36cbc..ff4d73f947a683ca 100644\n> > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> > > @@ -28,6 +28,12 @@ public:\n> > >  \tPipelineHandlerIPU3(CameraManager *manager);\n> > >  \t~PipelineHandlerIPU3();\n> > >\n> > > +\tstd::map<unsigned int, StreamConfiguration>\n> > > +\tstreamConfiguration(const Camera *camera,\n> > > +\t\t\t    const std::vector<Stream> &streams) const;\n> > > +\tint configureStreams(const Camera *camera,\n> > > +\t\t\t     std::map<unsigned int, StreamConfiguration> &config);\n> > > +\n> > >  \tbool match(DeviceEnumerator *enumerator);\n> > >\n> > >  private:\n> > > @@ -61,6 +67,32 @@ PipelineHandlerIPU3::~PipelineHandlerIPU3()\n> > >  \t\timgu_->release();\n> > >  }\n> > >\n> > > +std::map<unsigned int, StreamConfiguration>\n> > > +PipelineHandlerIPU3::streamConfiguration(const Camera *camera,\n> > > +\t\t\t\t\t const std::vector<Stream> &streams) const\n> > > +{\n> > > +\tstd::map<unsigned int, StreamConfiguration> configs;\n> > > +\n> > > +\tStreamConfiguration config;\n> > > +\n> > > +\tLOG(IPU3, Info) << \"TODO: Fetch stream configuration\";\n> > > +\n> > > +\tconfigs[0] = config;\n> > > +\n> > > +\treturn configs;\n> > > +}\n> > > +\n> > > +int PipelineHandlerIPU3::configureStreams(const Camera *camera,\n> > > +\t\t\t\t\t  std::map<unsigned int, StreamConfiguration> &config)\n> > > +{\n> > > +\tStreamConfiguration *cfg = &config[0];\n> > > +\n> > > +\tLOG(IPU3, Info) << \"TODO: Configure the camera for resolution \" <<\n> > > +\t\tcfg->width << \"x\" << cfg->height;\n> > > +\n> > > +\treturn 0;\n> > > +}\n> > > +\n> > >  bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)\n> > >  {\n> > >  \tDeviceMatch cio2_dm(\"ipu3-cio2\");\n> > > diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp\n> > > index bc4a8d7236be589d..bba4655a0a26b622 100644\n> > > --- a/src/libcamera/pipeline/uvcvideo.cpp\n> > > +++ b/src/libcamera/pipeline/uvcvideo.cpp\n> > > @@ -9,18 +9,27 @@\n> > >  #include <libcamera/stream.h>\n> > >\n> > >  #include \"device_enumerator.h\"\n> > > +#include \"log.h\"\n> > >  #include \"media_device.h\"\n> > >  #include \"pipeline_handler.h\"\n> > >  #include \"v4l2_device.h\"\n> > >\n> > >  namespace libcamera {\n> > >\n> > > +LOG_DEFINE_CATEGORY(UVC)\n> > > +\n> > >  class PipelineHandlerUVC : public PipelineHandler\n> > >  {\n> > >  public:\n> > >  \tPipelineHandlerUVC(CameraManager *manager);\n> > >  \t~PipelineHandlerUVC();\n> > >\n> > > +\tstd::map<unsigned int, StreamConfiguration>\n> > > +\tstreamConfiguration(const Camera *camera,\n> > > +\t\t\t    const std::vector<Stream> &streams) const;\n> > > +\tint configureStreams(const Camera *camera,\n> > > +\t\t\t     std::map<unsigned int, StreamConfiguration> &config);\n> > > +\n> > >  \tbool match(DeviceEnumerator *enumerator);\n> > >\n> > >  private:\n> > > @@ -42,6 +51,32 @@ PipelineHandlerUVC::~PipelineHandlerUVC()\n> > >  \t\tmedia_->release();\n> > >  }\n> > >\n> > > +std::map<unsigned int, StreamConfiguration>\n> > > +PipelineHandlerUVC::streamConfiguration(const Camera *camera,\n> > > +\t\t\t\t\tconst std::vector<Stream> &streams) const\n> > > +{\n> > > +\tstd::map<unsigned int, StreamConfiguration> configs;\n> > > +\n> > > +\tStreamConfiguration config;\n> > > +\n> > > +\tLOG(UVC, Info) << \"TODO: Fetch stream configuration\";\n> > > +\n> > > +\tconfigs[0] = config;\n> > > +\n> > > +\treturn configs;\n> > > +}\n> > > +\n> > > +int PipelineHandlerUVC::configureStreams(const Camera *camera,\n> > > +\t\t\t\t\t std::map<unsigned int, StreamConfiguration> &config)\n> > > +{\n> > > +\tStreamConfiguration *cfg = &config[0];\n> > > +\n> > > +\tLOG(UVC, Info) << \"TODO: Configure the camera for resolution \" <<\n> > > +\t\tcfg->width << \"x\" << cfg->height;\n> > > +\n> > > +\treturn 0;\n> > > +}\n> > > +\n> > >  bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)\n> > >  {\n> > >  \tDeviceMatch dm(\"uvcvideo\");\n> > > diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp\n> > > index c426a953aea1b3dd..c9810a8e192ac68b 100644\n> > > --- a/src/libcamera/pipeline/vimc.cpp\n> > > +++ b/src/libcamera/pipeline/vimc.cpp\n> > > @@ -9,17 +9,26 @@\n> > >  #include <libcamera/stream.h>\n> > >\n> > >  #include \"device_enumerator.h\"\n> > > +#include \"log.h\"\n> > >  #include \"media_device.h\"\n> > >  #include \"pipeline_handler.h\"\n> > >\n> > >  namespace libcamera {\n> > >\n> > > +LOG_DEFINE_CATEGORY(VIMC)\n> > > +\n> > >  class PipeHandlerVimc : public PipelineHandler\n> > >  {\n> > >  public:\n> > >  \tPipeHandlerVimc(CameraManager *manager);\n> > >  \t~PipeHandlerVimc();\n> > >\n> > > +\tstd::map<unsigned int, StreamConfiguration>\n> > > +\tstreamConfiguration(const Camera *camera,\n> > > +\t\t\t    const std::vector<Stream> &streams) const;\n> > > +\tint configureStreams(const Camera *camera,\n> > > +\t\t\t     std::map<unsigned int, StreamConfiguration> &config);\n> > > +\n> > >  \tbool match(DeviceEnumerator *enumerator);\n> > >\n> > >  private:\n> > > @@ -37,6 +46,32 @@ PipeHandlerVimc::~PipeHandlerVimc()\n> > >  \t\tmedia_->release();\n> > >  }\n> > >\n> > > +std::map<unsigned int, StreamConfiguration>\n> > > +PipeHandlerVimc::streamConfiguration(const Camera *camera,\n> > > +\t\t\t\t     const std::vector<Stream> &streams) const\n> > > +{\n> > > +\tstd::map<unsigned int, StreamConfiguration> configs;\n> > > +\n> > > +\tStreamConfiguration config;\n> > > +\n> > > +\tLOG(VIMC, Info) << \"TODO: Fetch stream configuration\";\n> > > +\n> > > +\tconfigs[0] = config;\n> > > +\n> > > +\treturn configs;\n> > > +}\n> > > +\n> > > +int PipeHandlerVimc::configureStreams(const Camera *camera,\n> > > +\t\t\t\t      std::map<unsigned int, StreamConfiguration> &config)\n> > > +{\n> > > +\tStreamConfiguration *cfg = &config[0];\n> > > +\n> > > +\tLOG(VIMC, Info) << \"TODO: Configure the camera for resolution \" <<\n> > > +\t\tcfg->width << \"x\" << cfg->height;\n> > > +\n> > > +\treturn 0;\n> > > +}\n> > > +\n> > >  bool PipeHandlerVimc::match(DeviceEnumerator *enumerator)\n> > >  {\n> > >  \tDeviceMatch dm(\"vimc\");\n> > > diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp\n> > > index 1c8640799f714686..ee6d80908f67d564 100644\n> > > --- a/src/libcamera/pipeline_handler.cpp\n> > > +++ b/src/libcamera/pipeline_handler.cpp\n> > > @@ -75,6 +75,40 @@ PipelineHandler::~PipelineHandler()\n> > >  {\n> > >  };\n> > >\n> > > +\n> > > +/**\n> > > + * \\fn PipelineHandler::streamConfiguration(const Camera *camera, * const std::vector<Stream> &streams)\n> >\n> > You don't need to specify the function parameters when the function\n> > isn't overloaded.\n> >\n> > > + * \\brief Retrieve a group of stream configurations for a specified camera\n> > > + * \\param[in] camera The camera to fetch the configuration from\n> > > + * \\param[in] streams An array of streams to fetch information about\n> > > + *\n> > > + * Retrieve the species camera's configuration for a specified group of streams.\n> > > + * The caller shall populate the \\a streams array with the streams it wish to\n> > > + * fetch the configuration from. The map of stream IDs and configuration\n> > > + * returned can then be examined by the caller to learn about the parameters for\n> > > + * the specified streams.\n> > > + *\n> > > + * The intended companion to this is \\a configureStreams() which can be used to\n> > > + * change the group of streams parameters.\n> > > + *\n> > > + * \\return A map of successfully retrieved stream IDs and configurations or an\n> > > + * empty map on error.\n> > > + */\n> > > +\n> > > +/**\n> > > + * \\fn PipelineHandler::configureStreams(const Camera *camera, std::map<unsigned int, StreamConfiguration> &config)\n> > > + * \\brief Configure a group of streams for capture\n> > > + * \\param[in] camera The camera to apply the configuration to\n> >\n> > You could simply say \"The camera to configure\".\n> >\n> > > + * \\param[in] config A map of stream configurations to apply\n> > > + *\n> > > + * Configure the specified group of streams for \\a camera according to the\n> > > + * configuration specified in \\a configs. The intended caller of this interface\n> > > + * is the Camera class which will receive configuration to apply from the\n> > > + * application.\n> > > + *\n> > > + * \\return 0 on success or a negative error code on error.\n> > > + */\n> > > +\n> > >  /**\n> > >   * \\fn PipelineHandler::match(DeviceEnumerator *enumerator)\n> > >   * \\brief Match media devices and create camera instances","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["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 93AD460DB7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 28 Jan 2019 22:57:52 +0100 (CET)","from pendragon.ideasonboard.com (85-76-73-159-nat.elisa-mobile.fi\n\t[85.76.73.159])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id CCD3D85;\n\tMon, 28 Jan 2019 22:57:50 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1548712672;\n\tbh=gteKbRCBcM01a/tCm08FQlHk13A/Be1uSt+kO7XZepk=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=FYtBpxdxcAtl6VW6Epe8/4h4Cx9FkF6tXfSW2NOkLlV/BYr+SGc3b1xzEMADwx3uJ\n\ttc+Xm356duaHzXbDI1+QnOthJXy2AWTogmSb+EqJgXdAvYjdfB81vK2iRdJd0xZUpH\n\tHI23DO+VtBjdI1G5J4Y1s0RAjO3KeRgYhfVgofQ4=","Date":"Mon, 28 Jan 2019 23:57:46 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>,\n\tlibcamera-devel@lists.libcamera.org","Message-ID":"<20190128215746.GC4332@pendragon.ideasonboard.com>","References":"<20190127002208.18913-1-niklas.soderlund@ragnatech.se>\n\t<20190127002208.18913-6-niklas.soderlund@ragnatech.se>\n\t<20190128000910.GD5154@pendragon.ideasonboard.com>\n\t<20190128113018.nirtpj4ksnipkitk@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20190128113018.nirtpj4ksnipkitk@uno.localdomain>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH v3 5/6] libcamera: pipeline: extend\n\tpipelines to support stream configuration","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","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>","X-List-Received-Date":"Mon, 28 Jan 2019 21:57:52 -0000"}}]