[{"id":5095,"web_url":"https://patchwork.libcamera.org/comment/5095/","msgid":"<20200606211839.GD7339@pendragon.ideasonboard.com>","date":"2020-06-06T21:18:39","subject":"Re: [libcamera-devel] [PATCH v2 04/10] libcamera: ipu3: Breakout\n\tstream assignment to new function","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 Sat, Jun 06, 2020 at 05:04:30PM +0200, Niklas Söderlund wrote:\n> Selecting which stream is the most suitable for the requested\n> configuration is mixed with adjusting the requested format when\n> validating configurations. This is hard to read and got worse when\n> support for Bayer formats was added, break it out to a separate\n\ns/, break/. Break/\n\n> function.\n> \n> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> ---\n> * Changes since v1\n> - Update commit message.\n> - Rename updateStreams() to assignStreams().\n> - Revert and keep old comment on how streams are picked.\n> - Do not modify behavior on how streams are picked which means\n>   assignStreams() now can't fail so no need for it to return an int,\n>   switch to void.\n> ---\n>  src/libcamera/pipeline/ipu3/ipu3.cpp | 79 ++++++++++++++++------------\n>  1 file changed, 44 insertions(+), 35 deletions(-)\n> \n> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> index f7363244e1d2d0ff..6df93eedb365b904 100644\n> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> @@ -190,6 +190,7 @@ private:\n>  \tstatic constexpr unsigned int IPU3_BUFFER_COUNT = 4;\n>  \tstatic constexpr unsigned int IPU3_MAX_STREAMS = 3;\n>  \n> +\tvoid assignStreams();\n>  \tvoid adjustStream(StreamConfiguration &cfg, bool scale);\n>  \n>  \t/*\n> @@ -256,6 +257,42 @@ IPU3CameraConfiguration::IPU3CameraConfiguration(Camera *camera,\n>  \tdata_ = data;\n>  }\n>  \n> +void IPU3CameraConfiguration::assignStreams()\n> +{\n> +\t/*\n> +\t * Verify and update all configuration entries, and assign a stream to\n> +\t * each of them. The viewfinder stream can scale, while the output\n> +\t * stream can crop only, so select the output stream when the requested\n> +\t * resolution is equal to the sensor resolution, and the viewfinder\n> +\t * stream otherwise.\n> +\t */\n> +\tstd::set<const IPU3Stream *> availableStreams = {\n> +\t\t&data_->outStream_,\n> +\t\t&data_->vfStream_,\n> +\t\t&data_->rawStream_,\n> +\t};\n> +\n> +\tstreams_.clear();\n> +\tstreams_.reserve(config_.size());\n> +\n> +\tfor (const StreamConfiguration &cfg : config_) {\n> +\t\tconst IPU3Stream *stream;\n> +\n> +\t\tif (cfg.pixelFormat.modifier() == IPU3_FORMAT_MOD_PACKED)\n> +\t\t\tstream = &data_->rawStream_;\n> +\t\telse if (cfg.size == sensorFormat_.size)\n> +\t\t\tstream = &data_->outStream_;\n> +\t\telse\n> +\t\t\tstream = &data_->vfStream_;\n> +\n> +\t\tif (availableStreams.find(stream) == availableStreams.end())\n> +\t\t\tstream = *availableStreams.begin();\n> +\n> +\t\tstreams_.push_back(stream);\n> +\t\tavailableStreams.erase(stream);\n\nI was going to comment that you should check that availableStreams\ndoesn't become empty, but then realized the caller already clamps the\nnumber of streams. Maybe a comment above this function should capture\nthe pre-conditions ?\n\nI think we'll have to extend the logic here to cover the case where the\nuser requests three streams and none of them has a raw format. The above\ncode will select the raw stream as the third stream. Wouldn't it make\nmore sense in that case to only return two streams ? This can be\ndiscussed and addressed separately from this patch, and in general I\nthink we need to document the heuristics that pipeline handlers shall\nimplement to validate the camera configuration.\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> +\t}\n> +}\n> +\n>  void IPU3CameraConfiguration::adjustStream(StreamConfiguration &cfg, bool scale)\n>  {\n>  \t/* The only pixel format the driver supports is NV12. */\n> @@ -342,40 +379,14 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n>  \tif (!sensorFormat_.size.width || !sensorFormat_.size.height)\n>  \t\tsensorFormat_.size = sensor->resolution();\n>  \n> -\t/*\n> -\t * Verify and update all configuration entries, and assign a stream to\n> -\t * each of them. The viewfinder stream can scale, while the output\n> -\t * stream can crop only, so select the output stream when the requested\n> -\t * resolution is equal to the sensor resolution, and the viewfinder\n> -\t * stream otherwise.\n> -\t */\n> -\tstd::set<const IPU3Stream *> availableStreams = {\n> -\t\t&data_->outStream_,\n> -\t\t&data_->vfStream_,\n> -\t\t&data_->rawStream_,\n> -\t};\n> -\n> -\tstreams_.clear();\n> -\tstreams_.reserve(config_.size());\n> +\t/* Assign streams to each configuration entry. */\n> +\tassignStreams();\n>  \n> +\t/* Verify and adjust configuration if needed. */\n>  \tfor (unsigned int i = 0; i < config_.size(); ++i) {\n>  \t\tStreamConfiguration &cfg = config_[i];\n> -\t\tconst PixelFormat pixelFormat = cfg.pixelFormat;\n> -\t\tconst Size size = cfg.size;\n> -\t\tconst IPU3Stream *stream;\n> -\n> -\t\tif (cfg.pixelFormat.modifier() == IPU3_FORMAT_MOD_PACKED)\n> -\t\t\tstream = &data_->rawStream_;\n> -\t\telse if (cfg.size == sensorFormat_.size)\n> -\t\t\tstream = &data_->outStream_;\n> -\t\telse\n> -\t\t\tstream = &data_->vfStream_;\n> -\n> -\t\tif (availableStreams.find(stream) == availableStreams.end())\n> -\t\t\tstream = *availableStreams.begin();\n> -\n> -\t\tLOG(IPU3, Debug)\n> -\t\t\t<< \"Assigned '\" << stream->name_ << \"' to stream \" << i;\n> +\t\tconst StreamConfiguration oldCfg = cfg;\n> +\t\tconst IPU3Stream *stream = streams_[i];\n>  \n>  \t\tif (stream->raw_) {\n>  \t\t\tconst auto &itFormat =\n> @@ -392,15 +403,13 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()\n>  \n>  \t\tcfg.bufferCount = IPU3_BUFFER_COUNT;\n>  \n> -\t\tif (cfg.pixelFormat != pixelFormat || cfg.size != size) {\n> +\t\tif (cfg.pixelFormat != oldCfg.pixelFormat ||\n> +\t\t    cfg.size != oldCfg.size) {\n>  \t\t\tLOG(IPU3, Debug)\n>  \t\t\t\t<< \"Stream \" << i << \" configuration adjusted to \"\n>  \t\t\t\t<< cfg.toString();\n>  \t\t\tstatus = Adjusted;\n>  \t\t}\n> -\n> -\t\tstreams_.push_back(stream);\n> -\t\tavailableStreams.erase(stream);\n>  \t}\n>  \n>  \treturn status;","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 1A9F061167\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat,  6 Jun 2020 23:18:59 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 7967230D;\n\tSat,  6 Jun 2020 23:18:58 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"LS3mR542\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1591478338;\n\tbh=myaGVt1LzE8noSlLtiWUn4kX1aHFvxVKRY6HkPC21t8=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=LS3mR542l9zzvqok3PPTUav5z/FwYJ8/gVGyANBbi+nTjwOjDGVA6xQR4RSKzE9vk\n\tSu8w6hDWRtGVTzObizefA75HfaMBLnu3RaILBtr7a4mKZ+bion+AThSsdajRxQ6+/J\n\tDvJmWMuAdLVSMR1Bo+SwTa+cYiqLyxOQ3PhemfYk=","Date":"Sun, 7 Jun 2020 00:18:39 +0300","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":"<20200606211839.GD7339@pendragon.ideasonboard.com>","References":"<20200606150436.1851700-1-niklas.soderlund@ragnatech.se>\n\t<20200606150436.1851700-5-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":"<20200606150436.1851700-5-niklas.soderlund@ragnatech.se>","Subject":"Re: [libcamera-devel] [PATCH v2 04/10] libcamera: ipu3: Breakout\n\tstream assignment to new function","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>","X-List-Received-Date":"Sat, 06 Jun 2020 21:18:59 -0000"}}]