{"id":1406,"url":"https://patchwork.libcamera.org/api/patches/1406/?format=json","web_url":"https://patchwork.libcamera.org/patch/1406/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/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":"<20190612004359.15772-11-niklas.soderlund@ragnatech.se>","date":"2019-06-12T00:43:53","name":"[libcamera-devel,v2,10/16] libcamera: stream: Add StreamFormats","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"8c52c7a7a55b16200d113739f0ea5717cee31b85","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/?format=json","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/1406/mbox/","series":[{"id":351,"url":"https://patchwork.libcamera.org/api/series/351/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=351","date":"2019-06-12T00:43:43","name":"libcamera: Add support for format information and validation","version":2,"mbox":"https://patchwork.libcamera.org/series/351/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/1406/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/1406/checks/","tags":{},"headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net\n\t[195.74.38.227])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9C23D61FAF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 12 Jun 2019 02:45:00 +0200 (CEST)","from bismarck.berto.se (unknown [89.233.230.99])\n\tby bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA\n\tid 37efd401-8cab-11e9-8601-0050569116f7;\n\tWed, 12 Jun 2019 02:44:22 +0200 (CEST)"],"X-Halon-ID":"37efd401-8cab-11e9-8601-0050569116f7","Authorized-sender":"niklas@soderlund.pp.se","From":"=?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","To":"libcamera-devel@lists.libcamera.org","Date":"Wed, 12 Jun 2019 02:43:53 +0200","Message-Id":"<20190612004359.15772-11-niklas.soderlund@ragnatech.se>","X-Mailer":"git-send-email 2.21.0","In-Reply-To":"<20190612004359.15772-1-niklas.soderlund@ragnatech.se>","References":"<20190612004359.15772-1-niklas.soderlund@ragnatech.se>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH v2 10/16] libcamera: stream: Add\n\tStreamFormats","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":"Wed, 12 Jun 2019 00:45:00 -0000"},"content":"Add a StreamFormats class which describes all the formats a stream can\nsupport. The object does not collect any formation itself but can\nsimplify user interactions with formats as it's able to translate a\nstream format range into discrete list and a discrete list to a range.\n\nSigned-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n---\n include/libcamera/stream.h |  16 +++\n src/libcamera/stream.cpp   | 228 +++++++++++++++++++++++++++++++++++++\n 2 files changed, 244 insertions(+)","diff":"diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\nindex e38c0e7e827d5888..48daf5ac23f55d85 100644\n--- a/include/libcamera/stream.h\n+++ b/include/libcamera/stream.h\n@@ -7,6 +7,7 @@\n #ifndef __LIBCAMERA_STREAM_H__\n #define __LIBCAMERA_STREAM_H__\n \n+#include <map>\n #include <string>\n #include <vector>\n \n@@ -18,6 +19,21 @@ namespace libcamera {\n class Camera;\n class Stream;\n \n+class StreamFormats\n+{\n+public:\n+\tStreamFormats();\n+\tStreamFormats(const std::map<unsigned int, std::vector<SizeRange>> &formats);\n+\n+\tstd::vector<unsigned int> pixelformats() const;\n+\tstd::vector<Size> sizes(unsigned int pixelformat) const;\n+\n+\tSizeRange range(unsigned int pixelformat) const;\n+\n+private:\n+\tstd::map<unsigned int, std::vector<SizeRange>> formats_;\n+};\n+\n struct StreamConfiguration {\n \tStreamConfiguration()\n \t\t: stream_(nullptr)\ndiff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\nindex 0c59a31a3a0501d3..52340c2644aac8d8 100644\n--- a/src/libcamera/stream.cpp\n+++ b/src/libcamera/stream.cpp\n@@ -7,9 +7,13 @@\n \n #include <libcamera/stream.h>\n \n+#include <algorithm>\n+#include <climits>\n #include <iomanip>\n #include <sstream>\n \n+#include \"log.h\"\n+\n /**\n  * \\file stream.h\n  * \\brief Video stream for a Camera\n@@ -32,6 +36,230 @@\n \n namespace libcamera {\n \n+LOG_DEFINE_CATEGORY(Stream)\n+\n+/**\n+ * \\class StreamFormats\n+ * \\brief Hold information about supported stream formats\n+ *\n+ * The StreamFormats class holds information about the pixel formats and frame\n+ * sizes a stream supports. The class groups size information by the pixel\n+ * format which can produce it.\n+ *\n+ * There are two ways to examine the size information, as a range or as a list\n+ * of discrete sizes. When sizes are viewed as a range it describes the minimum\n+ * and maximum width and height values. There is a possibility to supplement the\n+ * range description with a horizontal and vertical step. The step describes the\n+ * size in pixels from the minimum with/height.\n+ *\n+ * When sizes are viewed as a list of discrete sizes they describe exact\n+ * dimensions which can be selected and used.\n+ *\n+ * Pipeline handlers can create StreamFormats describing each pixel format using\n+ * either a range or a list of discrete sizes. The StreamFormats class attempts\n+ * to translate between the two different ways to view them. The translations\n+ * are performed as:\n+ *\n+ *  - If a pixel format is described as a list of discrete sizes then a range is\n+ *    created by taking the minimum and maximum width/height in the list. The\n+ *    step information is not recreated and is set to 0 to indicate it is\n+ *    generated.\n+ *\n+ *  - If a pixel format is described as a range then a list of discrete sizes\n+ *    which fits inside that range are selected from a list of common sizes. The\n+ *    step information is taken into consideration when generating the sizes.\n+ *\n+ * Applications examining sizes as a range with step values of 0 shall be\n+ * aware that the range are generated from a list of discrete sizes and there\n+ * could be a large quantity of possible Size combinations which may not\n+ * be supported by the Stream.\n+ *\n+ * All sizes retrieved from StreamFormats shall be treated as advisory and no\n+ * size shall be considered to be supported until its been verified using\n+ * CameraConfiguration::validate().\n+ */\n+\n+/**\n+ * \\brief Construct a empty StreamFormats object\n+ */\n+StreamFormats::StreamFormats()\n+{\n+}\n+\n+/**\n+ * \\brief Construct a StreamFormats object\n+ * \\param[in] formats A map of pixel formats to a sizes description\n+ */\n+StreamFormats::StreamFormats(const std::map<unsigned int, std::vector<SizeRange>> &formats)\n+\t: formats_(formats)\n+{\n+}\n+\n+/**\n+ * \\brief Retrieve the list of supported pixel formats\n+ * \\returns The list of supported pixel formats\n+ */\n+std::vector<unsigned int> StreamFormats::pixelformats() const\n+{\n+\tstd::vector<unsigned int> formats;\n+\n+\tfor (auto const &it : formats_)\n+\t\tformats.push_back(it.first);\n+\n+\treturn formats;\n+}\n+\n+/**\n+ * \\brief Retrieve the list of frame sizes\n+ * \\param[in] pixelformat Pixel format to retrieve sizes for\n+ *\n+ * If the sizes described for \\a pixelformat are discrete they are returned\n+ * directly. If the size described is a range a list of discrete sizes are\n+ * computed from a set list of common resolutions which fits inside the\n+ * described range. When computing the discrete list step values are considered\n+ * but there are no guarantees that all sizes computed are supported.\n+ *\n+ * \\returns List description of frame sizes\n+ */\n+std::vector<Size> StreamFormats::sizes(unsigned int pixelformat) const\n+{\n+\t/*\n+\t * Sizes to try and extract from ranges.\n+\t * \\todo Verify list of resolutions are good, current list compiled\n+\t * from v4l2 documentation and source code as well as lists of\n+\t * common frame sizes.\n+\t */\n+\tstatic const std::vector<Size> rangeDiscreteSizes = {\n+\t\tSize(160, 120),\n+\t\tSize(240, 160),\n+\t\tSize(320, 240),\n+\t\tSize(400, 240),\n+\t\tSize(480, 320),\n+\t\tSize(640, 360),\n+\t\tSize(640, 480),\n+\t\tSize(720, 480),\n+\t\tSize(720, 576),\n+\t\tSize(768, 480),\n+\t\tSize(800, 600),\n+\t\tSize(854, 480),\n+\t\tSize(960, 540),\n+\t\tSize(960, 640),\n+\t\tSize(1024, 576),\n+\t\tSize(1024, 600),\n+\t\tSize(1024, 768),\n+\t\tSize(1152, 864),\n+\t\tSize(1280, 1024),\n+\t\tSize(1280, 1080),\n+\t\tSize(1280, 720),\n+\t\tSize(1280, 800),\n+\t\tSize(1360, 768),\n+\t\tSize(1366, 768),\n+\t\tSize(1400, 1050),\n+\t\tSize(1440, 900),\n+\t\tSize(1536, 864),\n+\t\tSize(1600, 1200),\n+\t\tSize(1600, 900),\n+\t\tSize(1680, 1050),\n+\t\tSize(1920, 1080),\n+\t\tSize(1920, 1200),\n+\t\tSize(2048, 1080),\n+\t\tSize(2048, 1152),\n+\t\tSize(2048, 1536),\n+\t\tSize(2160, 1080),\n+\t\tSize(2560, 1080),\n+\t\tSize(2560, 1440),\n+\t\tSize(2560, 1600),\n+\t\tSize(2560, 2048),\n+\t\tSize(2960, 1440),\n+\t\tSize(3200, 1800),\n+\t\tSize(3200, 2048),\n+\t\tSize(3200, 2400),\n+\t\tSize(3440, 1440),\n+\t\tSize(3840, 1080),\n+\t\tSize(3840, 1600),\n+\t\tSize(3840, 2160),\n+\t\tSize(3840, 2400),\n+\t\tSize(4096, 2160),\n+\t\tSize(5120, 2160),\n+\t\tSize(5120, 2880),\n+\t\tSize(7680, 4320),\n+\t};\n+\tstd::vector<Size> sizes;\n+\n+\t/* Make sure pixel format exists. */\n+\tauto const &it = formats_.find(pixelformat);\n+\tif (it == formats_.end())\n+\t\treturn {};\n+\n+\t/* Try creating a list of discrete sizes. */\n+\tconst std::vector<SizeRange> &ranges = it->second;\n+\tbool discrete = true;\n+\tfor (const SizeRange &range : ranges) {\n+\t\tif (range.min != range.max) {\n+\t\t\tdiscrete = false;\n+\t\t\tbreak;\n+\t\t}\n+\t\tsizes.emplace_back(range.min);\n+\t}\n+\n+\t/* If discrete not possible generate from range. */\n+\tif (!discrete) {\n+\t\tif (ranges.size() != 1) {\n+\t\t\tLOG(Stream, Error) << \"Range format is ambiguous\";\n+\t\t\treturn {};\n+\t\t}\n+\n+\t\tconst SizeRange &limit = ranges.front();\n+\t\tsizes.clear();\n+\n+\t\tfor (const Size &size : rangeDiscreteSizes)\n+\t\t\tif (limit.contains(size))\n+\t\t\t\tsizes.push_back(size);\n+\t}\n+\n+\tstd::sort(sizes.begin(), sizes.end());\n+\n+\treturn sizes;\n+}\n+\n+/**\n+ * \\brief Retrieve the frame size range\n+ * \\param[in] pixelformat Pixel format to retrieve range for\n+ *\n+ * If the size described for \\a pixelformat is a range the range is returned\n+ * directly. If the sizes described are a list of discrete sizes a range is\n+ * computed from the minimum and maxim sizes in the list. The step values of\n+ * a computed range is set to 0 to indicate that the range is generated and\n+ * that the full range may not supported.\n+ *\n+ * \\returns Range description of frame size\n+ */\n+SizeRange StreamFormats::range(unsigned int pixelformat) const\n+{\n+\tauto const it = formats_.find(pixelformat);\n+\tif (it == formats_.end())\n+\t\treturn {};\n+\n+\tconst std::vector<SizeRange> &ranges = it->second;\n+\tif (ranges.size() == 1)\n+\t\treturn ranges[0];\n+\n+\tLOG(Stream, Debug) << \"Building range from discrete\";\n+\tSizeRange range(UINT_MAX, UINT_MAX, 0, 0);\n+\tfor (const SizeRange &limit : ranges) {\n+\t\tif (limit.min < range.min)\n+\t\t\trange.min = limit.min;\n+\n+\t\tif (limit.max > range.max)\n+\t\t\trange.max = limit.max;\n+\t}\n+\n+\trange.hStep = 0;\n+\trange.vStep = 0;\n+\n+\treturn range;\n+}\n+\n /**\n  * \\struct StreamConfiguration\n  * \\brief Configuration parameters for a stream\n","prefixes":["libcamera-devel","v2","10/16"]}