{"id":3878,"url":"https://patchwork.libcamera.org/api/1.1/patches/3878/?format=json","web_url":"https://patchwork.libcamera.org/patch/3878/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/1.1/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20200529110335.620503-2-jacopo@jmondi.org>","date":"2020-05-29T11:03:31","name":"[libcamera-devel,1/5] libcamera: formats: Make ImageFormats a templated class","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"9ba156a50736e5089d25bb6734e22b11e31dcf03","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/1.1/people/3/?format=json","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/3878/mbox/","series":[{"id":938,"url":"https://patchwork.libcamera.org/api/1.1/series/938/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=938","date":"2020-05-29T11:03:30","name":"ImageFormats' not dead","version":1,"mbox":"https://patchwork.libcamera.org/series/938/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/3878/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/3878/checks/","tags":{},"headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net\n\t[217.70.183.196])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3159D61012\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 29 May 2020 13:00:30 +0200 (CEST)","from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101])\n\t(Authenticated sender: jacopo@jmondi.org)\n\tby relay4-d.mail.gandi.net (Postfix) with ESMTPSA id 9C000E0009;\n\tFri, 29 May 2020 11:00:29 +0000 (UTC)"],"X-Originating-IP":"2.224.242.101","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"libcamera-devel@lists.libcamera.org","Date":"Fri, 29 May 2020 13:03:31 +0200","Message-Id":"<20200529110335.620503-2-jacopo@jmondi.org>","X-Mailer":"git-send-email 2.26.2","In-Reply-To":"<20200529110335.620503-1-jacopo@jmondi.org>","References":"<20200529110335.620503-1-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH 1/5] libcamera: formats: Make ImageFormats\n\ta templated class","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":"Fri, 29 May 2020 11:00:30 -0000"},"content":"The ImageFormats class was originally designed to be used by both\nV4L2VideoDevices and V4L2Subdevices. As video devices enumerates their\nimage formats using V4L2PixelFormat instances, the ImageFormats class\ncannot be used there anymore and it has been replaced by raw maps.\n\nPrepare to re-introduce usage of ImageFormats in the V4L2VideoDevice\nclass and its users by making ImageFormats a templated class that\nindexes the image sizes using on keys of variadic type.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n include/libcamera/internal/camera_sensor.h  |   2 +-\n include/libcamera/internal/formats.h        |  64 ++++++++++-\n include/libcamera/internal/v4l2_subdevice.h |   2 +-\n src/libcamera/formats.cpp                   | 117 +++++++++++++-------\n src/libcamera/v4l2_subdevice.cpp            |   6 +-\n test/v4l2_subdevice/list_formats.cpp        |   2 +-\n 6 files changed, 138 insertions(+), 55 deletions(-)","diff":"diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h\nindex d79bd9ce9d58..5c1d5789fe79 100644\n--- a/include/libcamera/internal/camera_sensor.h\n+++ b/include/libcamera/internal/camera_sensor.h\n@@ -75,7 +75,7 @@ private:\n \n \tstd::string model_;\n \n-\tImageFormats formats_;\n+\tImageFormats<uint32_t> formats_;\n \tSize resolution_;\n \tstd::vector<unsigned int> mbusCodes_;\n \tstd::vector<Size> sizes_;\ndiff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h\nindex 4092a93ef973..e20c031e857f 100644\n--- a/include/libcamera/internal/formats.h\n+++ b/include/libcamera/internal/formats.h\n@@ -18,18 +18,70 @@\n \n namespace libcamera {\n \n+template<typename T>\n class ImageFormats\n {\n public:\n-\tint addFormat(unsigned int format, const std::vector<SizeRange> &sizes);\n+\tusing iterator = typename std::map<T, std::vector<SizeRange>>::iterator;\n+\tusing const_iterator = typename std::map<T, std::vector<SizeRange>>::const_iterator;\n+\tusing value_type = typename std::map<T, std::vector<SizeRange>>::value_type;\n \n-\tbool isEmpty() const;\n-\tstd::vector<unsigned int> formats() const;\n-\tconst std::vector<SizeRange> &sizes(unsigned int format) const;\n-\tconst std::map<unsigned int, std::vector<SizeRange>> &data() const;\n+\titerator begin() { return data_.begin(); }\n+\tconst_iterator begin() const { return data_.begin(); }\n+\titerator end() { return data_.end(); }\n+\tconst_iterator end() const { return data_.end(); }\n+\n+\titerator find(const T format) { return data_.find(format); }\n+\tconst iterator find(T format) const { return data_.find(format); }\n+\n+\ttemplate<class... Args>\n+\tstd::pair<iterator, bool> emplace(Args&&... args)\n+\t{\n+\t\treturn data_.emplace(args...);\n+\t}\n+\n+\tint addFormat(T format, const std::vector<SizeRange> &sizes)\n+\t{\n+\t\tif (data_.find(format) != data_.end())\n+\t\t\treturn -EEXIST;\n+\n+\t\tdata_[format] = sizes;\n+\n+\t\treturn 0;\n+\t}\n+\n+\tbool isEmpty() const { return data_.empty(); }\n+\n+\tstd::vector<T> formats() const\n+\t{\n+\t\tstd::vector<T> formats;\n+\t\tformats.reserve(data_.size());\n+\n+\t\t/* \\todo: Should this be cached instead of computed each time? */\n+\t\tfor (auto const &it : data_)\n+\t\t\tformats.push_back(it.first);\n+\n+\t\treturn formats;\n+\t}\n+\n+\tconst std::vector<SizeRange> &sizes(T format) const\n+\t{\n+\t\tstatic const std::vector<SizeRange> empty;\n+\n+\t\tauto const &it = data_.find(format);\n+\t\tif (it == data_.end())\n+\t\t\treturn empty;\n+\n+\t\treturn it->second;\n+\t}\n+\n+\tconst std::map<T, std::vector<SizeRange>> &data() const\n+\t{\n+\t\treturn data_;\n+\t}\n \n private:\n-\tstd::map<unsigned int, std::vector<SizeRange>> data_;\n+\tstd::map<T, std::vector<SizeRange>> data_;\n };\n \n class PixelFormatInfo\ndiff --git a/include/libcamera/internal/v4l2_subdevice.h b/include/libcamera/internal/v4l2_subdevice.h\nindex 1be454f0ddda..0ce6da48f58a 100644\n--- a/include/libcamera/internal/v4l2_subdevice.h\n+++ b/include/libcamera/internal/v4l2_subdevice.h\n@@ -51,7 +51,7 @@ public:\n \tint setSelection(unsigned int pad, unsigned int target,\n \t\t\t Rectangle *rect);\n \n-\tImageFormats formats(unsigned int pad);\n+\tImageFormats<uint32_t> formats(unsigned int pad);\n \n \tint getFormat(unsigned int pad, V4L2SubdeviceFormat *format,\n \t\t      Whence whence = ActiveFormat);\ndiff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp\nindex 2ac3b412ecdb..a7922077d9c5 100644\n--- a/src/libcamera/formats.cpp\n+++ b/src/libcamera/formats.cpp\n@@ -22,20 +22,85 @@ LOG_DEFINE_CATEGORY(Formats)\n \n /**\n  * \\class ImageFormats\n- * \\brief Describe V4L2Device and V4L2SubDevice image formats\n+ * \\brief Describe V4L2Device and V4L2SubDevice image formats and associated\n+ * image resolutions\n  *\n- * This class stores a list of image formats, each associated with a\n+ * This class stores a list of image formats, each of them associated with a\n  * corresponding set of image sizes. It is used to describe the formats and\n  * sizes supported by a V4L2Device or V4L2Subdevice.\n  *\n- * Formats are stored as an integer. When used for a V4L2Device, the image\n- * formats are fourcc pixel formats. When used for a V4L2Subdevice they are\n- * media bus codes. Both are defined by the V4L2 specification.\n+ * When used for a V4L2Device, the image formats are V4L2PixelFormat instances.\n+ * When used for a V4L2Subdevice formats are integer media bus codes.\n  *\n  * Sizes are stored as a list of SizeRange.\n  */\n \n /**\n+ * \\typedef ImageFormats::iterator\n+ * \\brief Iterator for the formats map\n+ */\n+\n+/**\n+ * \\typedef ImageFormats::const_iterator\n+ * \\brief Const iterator for the formats map\n+ */\n+\n+/**\n+ * \\typedef ImageFormats::value_type\n+ * \\brief Value type of the entries in the formats map\n+ */\n+\n+/**\n+ * \\fn iterator ImageFormats<T>::begin()\n+ * \\brief Retrieve an iterator to the first element in the formats map\n+ * \\return An iterator to the first format map\n+ */\n+\n+/**\n+ * \\fn const_iterator ImageFormats<T>::begin() const\n+ * \\brief Retrieve an const iterator to the first element in the formats map\n+ * \\return A const iterator to the first format map\n+ */\n+\n+/**\n+ * \\fn iterator ImageFormats<T>::end()\n+ * \\brief Retrieve an iterator pointing to the past-the-end element in the\n+ * formats map\n+ * \\return An iterator to the element following the last format\n+ */\n+\n+/**\n+ * \\fn const_iterator ImageFormats<T>::end() const\n+ * \\brief Retrieve a const iterator pointing to the past-the-end element in the\n+ * formats map\n+ * \\return A const iterator to the element following the last format\n+ */\n+\n+/**\n+ * \\fn iterator ImageFormats::find(const T format)\n+ * \\brief Find an element with key equal to \\a format\n+ * \\param[in] format The format to search for\n+ * \\return An iterator to the vector of sizes associated with \\a format\n+ */\n+\n+/**\n+ * \\fn const_iterator ImageFormats::find(const T format) const\n+ * \\brief Find a const element with key equal to \\a format\n+ * \\param[in] format The format to search for\n+ * \\return An const iterator to the vector of sizes associated with \\a format\n+ */\n+\n+/**\n+ * \\fn std::pair<iterator, bool> ImageFormats::emplace(Args&&... args)\n+ * \\brief Insert a new element in the formats map constructed in place with the\n+ * given \\a args\n+ * \\param[in] args The argument pack used to construct the new entry in place\n+ * \\return A pair consisting of an iterator to the inserted element, and a bool\n+ * denoting whether the insertion took place\n+ */\n+\n+/**\n+ * \\fn ImageFormats<T>::addFormat(T format, const std::vector<SizeRange> &sizes)\n  * \\brief Add a format and corresponding sizes to the description\n  * \\param[in] format Pixel format or media bus code to describe\n  * \\param[in] sizes List of supported size ranges for the format\n@@ -43,42 +108,21 @@ LOG_DEFINE_CATEGORY(Formats)\n  * \\return 0 on success or a negative error code otherwise\n  * \\retval -EEXIST The format is already described\n  */\n-int ImageFormats::addFormat(unsigned int format, const std::vector<SizeRange> &sizes)\n-{\n-\tif (data_.find(format) != data_.end())\n-\t\treturn -EEXIST;\n-\n-\tdata_[format] = sizes;\n-\n-\treturn 0;\n-}\n \n /**\n+ * \\fn ImageFormats<T>::isEmpty() const\n  * \\brief Check if the list of devices supported formats is empty\n  * \\return True if the list of supported formats is empty\n  */\n-bool ImageFormats::isEmpty() const\n-{\n-\treturn data_.empty();\n-}\n \n /**\n+ * \\fn ImageFormats<T>::formats() const\n  * \\brief Retrieve a list of all supported image formats\n  * \\return List of pixel formats or media bus codes\n  */\n-std::vector<unsigned int> ImageFormats::formats() const\n-{\n-\tstd::vector<unsigned int> formats;\n-\tformats.reserve(data_.size());\n-\n-\t/* \\todo: Should this be cached instead of computed each time? */\n-\tfor (auto const &it : data_)\n-\t\tformats.push_back(it.first);\n-\n-\treturn formats;\n-}\n \n /**\n+ * \\fn ImageFormats<T>::sizes(T format) const\n  * \\brief Retrieve all sizes for a specific format\n  * \\param[in] format The pixel format or mbus code\n  *\n@@ -88,25 +132,12 @@ std::vector<unsigned int> ImageFormats::formats() const\n  * \\return The list of image sizes supported for \\a format, or an empty list if\n  * the format is not supported\n  */\n-const std::vector<SizeRange> &ImageFormats::sizes(unsigned int format) const\n-{\n-\tstatic const std::vector<SizeRange> empty;\n-\n-\tauto const &it = data_.find(format);\n-\tif (it == data_.end())\n-\t\treturn empty;\n-\n-\treturn it->second;\n-}\n \n /**\n+ * \\fn ImageFormats<T>::data() const\n  * \\brief Retrieve the map that associates formats to image sizes\n  * \\return The map that associates formats to image sizes\n  */\n-const std::map<unsigned int, std::vector<SizeRange>> &ImageFormats::data() const\n-{\n-\treturn data_;\n-}\n \n /**\n  * \\class PixelFormatInfo\ndiff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp\nindex 7aefc1be032d..9fa20e84a904 100644\n--- a/src/libcamera/v4l2_subdevice.cpp\n+++ b/src/libcamera/v4l2_subdevice.cpp\n@@ -320,16 +320,16 @@ int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target,\n  *\n  * \\return A list of the supported device formats\n  */\n-ImageFormats V4L2Subdevice::formats(unsigned int pad)\n+ImageFormats<uint32_t> V4L2Subdevice::formats(unsigned int pad)\n {\n-\tImageFormats formats;\n+\tImageFormats<uint32_t> formats;\n \n \tif (pad >= entity_->pads().size()) {\n \t\tLOG(V4L2, Error) << \"Invalid pad: \" << pad;\n \t\treturn {};\n \t}\n \n-\tfor (unsigned int code : enumPadCodes(pad)) {\n+\tfor (uint32_t code : enumPadCodes(pad)) {\n \t\tstd::vector<SizeRange> sizes = enumPadSizes(pad, code);\n \t\tif (sizes.empty())\n \t\t\treturn {};\ndiff --git a/test/v4l2_subdevice/list_formats.cpp b/test/v4l2_subdevice/list_formats.cpp\nindex 25503c3334e5..f66bb633fb00 100644\n--- a/test/v4l2_subdevice/list_formats.cpp\n+++ b/test/v4l2_subdevice/list_formats.cpp\n@@ -48,7 +48,7 @@ void ListFormatsTest::printFormats(unsigned int pad,\n int ListFormatsTest::run()\n {\n \t/* List all formats available on existing \"Scaler\" pads. */\n-\tImageFormats formats;\n+\tImageFormats<uint32_t> formats;\n \n \tformats = scaler_->formats(0);\n \tif (formats.isEmpty()) {\n","prefixes":["libcamera-devel","1/5"]}