[{"id":1321,"web_url":"https://patchwork.libcamera.org/comment/1321/","msgid":"<20190409134958.GA4578@pendragon.ideasonboard.com>","date":"2019-04-09T13:49:58","subject":"Re: [libcamera-devel] [PATCH v4 7/8] libcamera: camera: Add\n\tCameraConfiguration","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 Mon, Apr 08, 2019 at 03:48:16PM +0200, Niklas Söderlund wrote:\n> To properly support both multiple streams and stream usages the library\n> must provide a method to map the stream usages to the returned streams\n> configurations. Add a camera configuration object to handle this\n> mapping.\n> \n> Applications can iterate over the returned camera configuration to\n> retrieve the streams selected by the library in the same order as the\n> usages it provided to the library.\n> \n> Application can use the operator[] to retrieve the stream pointer and\n\ns/Application/Applications/\n\n> the stream configuration. Using a numerical index retrieves the stream\n> pointer, the numerical indexes corresponds to the insertion order of\n> usages by the application, using the stream pointer retrieves the\n\ns/by the application/in the CameraConfiguration/ (as libcamera will also\ninsert usages)\n\n> stream's configuration.\n> \n> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> ---\n>  include/libcamera/camera.h |  29 ++++++\n>  src/libcamera/camera.cpp   | 192 +++++++++++++++++++++++++++++++++++++\n>  2 files changed, 221 insertions(+)\n> \n> diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h\n> index 0386671c902e55e8..6038da63e9c5c67f 100644\n> --- a/include/libcamera/camera.h\n> +++ b/include/libcamera/camera.h\n> @@ -24,6 +24,35 @@ class Stream;\n>  class StreamConfiguration;\n>  class StreamUsage;\n>  \n> +class CameraConfiguration\n> +{\n> +public:\n> +\tusing iterator = std::vector<Stream *>::iterator;\n> +\tusing const_iterator = std::vector<Stream *>::const_iterator;\n> +\n> +\tCameraConfiguration();\n> +\n> +\titerator begin();\n> +\titerator end();\n> +\tconst_iterator begin() const;\n> +\tconst_iterator end() const;\n> +\n> +\tbool isValid() const;\n> +\tbool isEmpty() const;\n> +\tstd::size_t size() const;\n> +\n> +\tStream *front();\n> +\tconst Stream *front() const;\n> +\n> +\tStream *operator[](unsigned int index) const;\n> +\tStreamConfiguration &operator[](Stream *stream);\n> +\tconst StreamConfiguration &operator[](Stream *stream) const;\n> +\n> +private:\n> +\tstd::vector<Stream *> order_;\n> +\tstd::map<Stream *, StreamConfiguration> config_;\n> +};\n> +\n>  class Camera final\n>  {\n>  public:\n> diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp\n> index 63fde0ffc3d02d6c..c1b9561304b04ab5 100644\n> --- a/src/libcamera/camera.cpp\n> +++ b/src/libcamera/camera.cpp\n> @@ -39,6 +39,198 @@ namespace libcamera {\n>  \n>  LOG_DECLARE_CATEGORY(Camera)\n>  \n> +/**\n> + * \\class CameraConfiguration\n> + * \\brief Hold configuration for streams of the camera\n> +\n> + * The CameraConfiguration holds an ordered list of streams and their associated\n> + * StreamConfiguration. From a data storage point of view, the class operates as\n> + * a map of Stream pointers to StreamConfiguration, with entries accessed with\n> + * operator[](Stream *). Accessing an entry for a Stream pointer not yet stored\n> + * in the configuration inserts a new empty entry.\n> + *\n> + * The class also suppors iterators, and from that point of view operates as a\n> + * vector of Stream pointers. The streams are iterated in insertion order, and\n> + * the operator[](int) returns the Stream pointer based on its insertion index.\n> + * Accessing a stream with an invalid index returns a null pointer.\n> + */\n> +\n> +/**\n> + * \\typedef CameraConfiguration::iterator\n> + * \\brief Iterator for the streams in the configuration\n> + */\n> +\n> +/**\n> + * \\typedef CameraConfiguration::const_iterator\n> + * \\brief Const iterator for the streams in the configuration\n> + */\n> +\n> +/**\n> + * \\brief Create an empty camera configuration\n> + */\n> +CameraConfiguration::CameraConfiguration()\n> +\t: order_({}), config_({})\n> +{\n> +}\n> +\n> +/**\n> + * \\brief Retrieve an iterator to the first stream in the sequence\n> + *\n> + * \\return An iterator to the first stream\n> + */\n> +std::vector<Stream *>::iterator CameraConfiguration::begin()\n> +{\n> +\treturn order_.begin();\n> +}\n> +\n> +/**\n> + * \\brief Retrieve an iterator pointing to the past-the-end stream in the\n> + * sequence\n> + *\n> + * \\return An iterator to the element following the last stream\n> + */\n> +std::vector<Stream *>::iterator CameraConfiguration::end()\n> +{\n> +\treturn order_.end();\n> +}\n> +\n> +/**\n> + * \\brief Retrieve a const iterator to the first element of the streams\n> + *\n> + * \\return A const iterator to the first stream\n> + */\n> +std::vector<Stream *>::const_iterator CameraConfiguration::begin() const\n> +{\n> +\treturn order_.begin();\n> +}\n> +\n> +/**\n> + * \\brief Retrieve a const iterator pointing to the past-the-end stream in the\n> + * sequence\n> + *\n> + * \\return A const iterator to the element following the last stream\n> + */\n> +std::vector<Stream *>::const_iterator CameraConfiguration::end() const\n> +{\n> +\treturn order_.end();\n> +}\n> +\n> +/**\n> + * \\brief Check if the camera configuration is valid\n> + *\n> + * A camera configuration is deemed to be valid if it contains at least one\n> + * stream configuration and that all stream configurations contain valid\n\ns/that all/all/\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> + * information. Stream configurations are deemed to be valid if all fields are\n> + * none zero.\n> + *\n> + * \\return True if the configuration is valid\n> + */\n> +bool CameraConfiguration::isValid() const\n> +{\n> +\tif (isEmpty())\n> +\t\treturn false;\n> +\n> +\tfor (auto const &it : config_) {\n> +\t\tconst StreamConfiguration &conf = it.second;\n> +\n> +\t\tif (conf.width == 0 || conf.height == 0 ||\n> +\t\t    conf.pixelFormat == 0 || conf.bufferCount == 0)\n> +\t\t\treturn false;\n> +\t}\n> +\n> +\treturn true;\n> +}\n> +\n> +/**\n> + * \\brief Check if the camera configuration is empty\n> + *\n> + * \\return True if the configuration is empty\n> + */\n> +bool CameraConfiguration::isEmpty() const\n> +{\n> +\treturn order_.empty();\n> +}\n> +\n> +/**\n> + * \\brief Retrieve the number of stream configurations\n> + *\n> + * \\return Number of stream configurations\n> + */\n> +std::size_t CameraConfiguration::size() const\n> +{\n> +\treturn order_.size();\n> +}\n> +\n> +/**\n> + * \\brief Access the first stream in the configuration\n> + *\n> + * \\return The first stream in the configuration\n> + */\n> +Stream *CameraConfiguration::front()\n> +{\n> +\treturn order_.front();\n> +}\n> +\n> +/**\n> + * \\brief Access the first stream in the configuration\n> + *\n> + * \\return The first const stream pointer in the configuration\n> + */\n> +const Stream *CameraConfiguration::front() const\n> +{\n> +\treturn order_.front();\n> +}\n> +\n> +/**\n> + * \\brief Retrieve a stream pointer from index\n> + * \\param[in] index Numerical index\n> + *\n> + * The \\a index represents the zero based insertion order of stream and stream\n> + * configuration into the camera configuration.\n> + *\n> + * \\return The stream pointer at index, or a nullptr if the index is out of\n> + * bounds\n> + */\n> +Stream *CameraConfiguration::operator[](unsigned int index) const\n> +{\n> +\tif (index >= order_.size())\n> +\t\treturn nullptr;\n> +\n> +\treturn order_.at(index);\n> +}\n> +\n> +/**\n> + * \\brief Retrieve a reference to a stream configuration\n> + * \\param[in] stream Stream to retrieve configuration for\n> + *\n> + * If the camera configuration does not yet contain a configuration for\n> + * the requested stream, create and return an empty stream configuration.\n> + *\n> + * \\return The configuration for the stream\n> + */\n> +StreamConfiguration &CameraConfiguration::operator[](Stream *stream)\n> +{\n> +\tif (config_.find(stream) == config_.end())\n> +\t\torder_.push_back(stream);\n> +\n> +\treturn config_[stream];\n> +}\n> +\n> +/**\n> + * \\brief Retrieve a const reference to a stream configuration\n> + * \\param[in] stream Stream to retrieve configuration for\n> + *\n> + * No new stream configuration is created if called with \\a stream that is not\n> + * already part of the camera configuration, doing so is an invalid operation\n> + * and results in undefined behaviour.\n> + *\n> + * \\return The configuration for the stream\n> + */\n> +const StreamConfiguration &CameraConfiguration::operator[](Stream *stream) const\n> +{\n> +\treturn config_.at(stream);\n> +}\n> +\n>  /**\n>   * \\class Camera\n>   * \\brief Camera device","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 B1DAB60DB4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  9 Apr 2019 15:50:08 +0200 (CEST)","from pendragon.ideasonboard.com (unknown\n\t[IPv6:2a02:2788:66a:3eb:e14:8605:25ce:b577])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 16E6E33A;\n\tTue,  9 Apr 2019 15:50:08 +0200 (CEST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1554817808;\n\tbh=s8mm266UJV4ryHZmc5BEEqUz9anaUAu9cB3T+uUkg+M=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=jKFgz7zbECNIb+xRNeRRrgbiXO7TBNznBA6aM/vV8rBXncH2L5icVF0QJbZpcA2EB\n\t07bqs3lJk1sBpfLuKHv5+Pg8Y6k4AeSf4kjY+73lwQu/yx/zuKpFCNH5Lt19YGxQs2\n\t+mxy0pXZdkwkfImMDIMhP/Il50viXt6v9L0+sgZo=","Date":"Tue, 9 Apr 2019 16:49:58 +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":"<20190409134958.GA4578@pendragon.ideasonboard.com>","References":"<20190408134817.15247-1-niklas.soderlund@ragnatech.se>\n\t<20190408134817.15247-8-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":"<20190408134817.15247-8-niklas.soderlund@ragnatech.se>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH v4 7/8] libcamera: camera: Add\n\tCameraConfiguration","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":"Tue, 09 Apr 2019 13:50:09 -0000"}}]