Show a patch.

GET /api/patches/840/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 840,
    "url": "https://patchwork.libcamera.org/api/patches/840/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/840/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20190402005406.25097-3-niklas.soderlund@ragnatech.se>",
    "date": "2019-04-02T00:54:04",
    "name": "[libcamera-devel,2/4] cam: Add support to specify multiple stream configurations with hints",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "d0a2fd59b7be72182af57dd8ab01dbe4787f3964",
    "submitter": {
        "id": 5,
        "url": "https://patchwork.libcamera.org/api/people/5/?format=api",
        "name": "Niklas Söderlund",
        "email": "niklas.soderlund@ragnatech.se"
    },
    "delegate": {
        "id": 16,
        "url": "https://patchwork.libcamera.org/api/users/16/?format=api",
        "username": "neg",
        "first_name": "Niklas",
        "last_name": "Söderlund",
        "email": "niklas.soderlund@ragnatech.se"
    },
    "mbox": "https://patchwork.libcamera.org/patch/840/mbox/",
    "series": [
        {
            "id": 228,
            "url": "https://patchwork.libcamera.org/api/series/228/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=228",
            "date": "2019-04-02T00:54:02",
            "name": "cam: Add support to specify multiple stream configurations with hints",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/228/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/840/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/840/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<niklas.soderlund@ragnatech.se>",
        "Received": [
            "from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net\n\t[195.74.38.228])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 401AC60DB2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  2 Apr 2019 02:54:35 +0200 (CEST)",
            "from bismarck.berto.se (unknown [89.233.230.99])\n\tby bin-vsp-out-01.atm.binero.net (Halon) with ESMTPA\n\tid e15b54bf-54e1-11e9-846a-005056917a89;\n\tTue, 02 Apr 2019 02:54:33 +0200 (CEST)"
        ],
        "X-Halon-ID": "e15b54bf-54e1-11e9-846a-005056917a89",
        "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": "Tue,  2 Apr 2019 02:54:04 +0200",
        "Message-Id": "<20190402005406.25097-3-niklas.soderlund@ragnatech.se>",
        "X-Mailer": "git-send-email 2.21.0",
        "In-Reply-To": "<20190402005406.25097-1-niklas.soderlund@ragnatech.se>",
        "References": "<20190402005406.25097-1-niklas.soderlund@ragnatech.se>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH 2/4] cam: Add support to specify multiple\n\tstream configurations with hints",
        "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, 02 Apr 2019 00:54:35 -0000"
    },
    "content": "Extend the cam tool to allow configuring more then one stream. Add an\noptional parameter to the --stream option to allow specifying a usage\nhint for the stream. The usage hint is passed to libcamera to allow it\nto make better decisions on which stream to use.\n\nTo allow multiple streams to work creation of requests needs to be\nreworked to be limit the number of requests to match the stream with the\nleasts number of buffers. This should be improved in the future as the\ntool and the library evolves.\n\nSigned-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n---\n src/cam/main.cpp | 76 ++++++++++++++++++++++++++++++++++++++++--------\n 1 file changed, 64 insertions(+), 12 deletions(-)",
    "diff": "diff --git a/src/cam/main.cpp b/src/cam/main.cpp\nindex d3f1f341d44e7f98..1bf28ca8eb8c6da7 100644\n--- a/src/cam/main.cpp\n+++ b/src/cam/main.cpp\n@@ -7,6 +7,7 @@\n \n #include <iomanip>\n #include <iostream>\n+#include <limits.h>\n #include <map>\n #include <signal.h>\n #include <string.h>\n@@ -17,6 +18,8 @@\n #include \"event_loop.h\"\n #include \"options.h\"\n \n+#define MIN(a, b) ((a) < (b) ? (a) : (b))\n+\n using namespace libcamera;\n \n OptionsParser::Options options;\n@@ -42,6 +45,9 @@ void signalHandler(int signal)\n static int parseOptions(int argc, char *argv[])\n {\n \tKeyValueParser streamKeyValue;\n+\tstreamKeyValue.addOption(\"hint\", OptionString,\n+\t\t\t\t \"Usage hint for the stream (viewfinder, video, still)\",\n+\t\t\t\t ArgumentRequired);\n \tstreamKeyValue.addOption(\"width\", OptionInteger, \"Width in pixels\",\n \t\t\t\t ArgumentRequired);\n \tstreamKeyValue.addOption(\"height\", OptionInteger, \"Height in pixels\",\n@@ -61,7 +67,7 @@ static int parseOptions(int argc, char *argv[])\n \t\t\t \"The default file name is 'frame-#.bin'.\",\n \t\t\t \"file\", ArgumentOptional, \"filename\");\n \tparser.addOption(OptStream, &streamKeyValue,\n-\t\t\t \"Set configuration of the camera's streams\", \"stream\");\n+\t\t\t \"Set configuration of the camera's streams\", \"stream\", true);\n \tparser.addOption(OptHelp, OptionNone, \"Display this help message\",\n \t\t\t \"help\");\n \tparser.addOption(OptList, OptionNone, \"List all cameras\", \"list\");\n@@ -80,12 +86,48 @@ static int parseOptions(int argc, char *argv[])\n \n static int prepare_camera_config(std::map<Stream *, StreamConfiguration> *config)\n {\n-\tstd::set<Stream *> streams = camera->streams();\n-\t*config = camera->streamConfiguration({ Video() });\n-\tStream *stream = config->begin()->first;\n+\tstd::vector<StreamHint> hints;\n \n-\tif (options.isSet(OptStream)) {\n-\t\tKeyValueParser::Options conf = options[OptStream];\n+\t/* If no configuration is provided assume a single video stream. */\n+\tif (!options.isSet(OptStream)) {\n+\t\t*config = camera->streamConfiguration({ Video() });\n+\t\treturn 0;\n+\t}\n+\n+\t/* Use hints and get a default configuration. */\n+\tfor (auto const &value : options[OptStream].toArray()) {\n+\t\tKeyValueParser::Options conf = value.toKeyValues();\n+\n+\t\tif (!conf.isSet(\"hint\"))\n+\t\t\thints.push_back(Video());\n+\t\telse if (conf[\"hint\"].toString() == \"viewfinder\")\n+\t\t\thints.push_back(Viewfinder(conf[\"width\"],\n+\t\t\t\t\t\t   conf[\"height\"]));\n+\t\telse if (conf[\"hint\"].toString() == \"video\")\n+\t\t\thints.push_back(Video());\n+\t\telse if (conf[\"hint\"].toString() == \"still\")\n+\t\t\thints.push_back(Still());\n+\t\telse {\n+\t\t\tstd::cerr << \"Unknown stream hint \"\n+\t\t\t\t  << conf[\"hint\"].toString() << std::endl;\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\t*config = camera->streamConfiguration(hints);\n+\n+\tif (config->size() != options[OptStream].toArray().size()) {\n+\t\tstd::cerr << \"Failed to get default stream configuration\"\n+\t\t\t  << std::endl;\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Apply configuration explicitly requested. */\n+\tstd::map<Stream *, StreamConfiguration>::iterator it = config->begin();\n+\tfor (auto const &value : options[OptStream].toArray()) {\n+\t\tKeyValueParser::Options conf = value.toKeyValues();\n+\t\tStream *stream = it->first;\n+\t\tit++;\n \n \t\tif (conf.isSet(\"width\"))\n \t\t\t(*config)[stream].width = conf[\"width\"];\n@@ -137,7 +179,6 @@ static void requestComplete(Request *request, const std::map<Stream *, Buffer *>\n static int capture()\n {\n \tstd::map<Stream *, StreamConfiguration> config;\n-\tstd::vector<Request *> requests;\n \tint ret;\n \n \tret = prepare_camera_config(&config);\n@@ -152,8 +193,6 @@ static int capture()\n \t\treturn ret;\n \t}\n \n-\tStream *stream = config.begin()->first;\n-\n \tret = camera->allocateBuffers();\n \tif (ret) {\n \t\tstd::cerr << \"Failed to allocate buffers\"\n@@ -163,9 +202,18 @@ static int capture()\n \n \tcamera->requestCompleted.connect(requestComplete);\n \n-\tBufferPool &pool = stream->bufferPool();\n+\t/* Figure out which stream have least number of buffers. */\n+\tunsigned int nbuffers = UINT_MAX;\n+\tfor (auto const &it : config)\n+\t\tnbuffers = MIN(nbuffers, it.first->bufferPool().count());\n \n-\tfor (Buffer &buffer : pool.buffers()) {\n+\t/*\n+\t * TODO: make cam tool smarter to support still capture by for\n+\t * example pushing a button. For now run all streams all the time.\n+\t */\n+\n+\tstd::vector<Request *> requests;\n+\tfor (unsigned int i = 0; i < nbuffers; i++) {\n \t\tRequest *request = camera->createRequest();\n \t\tif (!request) {\n \t\t\tstd::cerr << \"Can't create request\" << std::endl;\n@@ -174,7 +222,11 @@ static int capture()\n \t\t}\n \n \t\tstd::map<Stream *, Buffer *> map;\n-\t\tmap[stream] = &buffer;\n+\t\tfor (auto const &it : config) {\n+\t\t\tStream *stream = it.first;\n+\t\t\tmap[stream] = &stream->bufferPool().buffers()[i];\n+\t\t}\n+\n \t\tret = request->setBuffers(map);\n \t\tif (ret < 0) {\n \t\t\tstd::cerr << \"Can't set buffers for request\" << std::endl;\n",
    "prefixes": [
        "libcamera-devel",
        "2/4"
    ]
}